Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 188 additions & 72 deletions app/(site)/docs/installation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,93 @@ import { InstallationTabs } from "@/components/docs/installation-tabs";
import Image from "next/image";
import { useTheme } from "next-themes";

export default function InstallationPage() {
const [selectedPlatform, setSelectedPlatform] = React.useState("expo");
const { resolvedTheme } = useTheme();
const [mounted, setMounted] = React.useState(false);

React.useEffect(() => {
setMounted(true);
}, []);
const InstallationPageSkeleton = () => {
return (
<div className="container max-w-3xl py-10 animate-pulse">
{/* Header skeleton */}
<div className="space-y-6">
<div className="space-y-4">
<div className="h-10 bg-muted rounded-md w-1/2"></div>
<div className="h-6 bg-muted rounded-md w-full"></div>
<div className="h-6 bg-muted rounded-md w-4/5"></div>
</div>

if (!mounted) {
return (
<div className="space-y-8">
<div>
<h1 className="text-3xl font-bold tracking-tight">Installation</h1>
<p className="text-muted-foreground text-lg mt-2">
How to install dependencies and structure your app.
</p>
{/* Info banner skeleton */}
<div className="rounded-lg border-2 p-4">
<div className="flex items-center gap-3">
<div className="rounded-full bg-muted p-2 w-9 h-9"></div>
<div className="h-5 bg-muted rounded-md flex-1"></div>
</div>
</div>
</div>

{/* Platform selection skeleton */}
<div className="mt-12 space-y-8">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="relative overflow-hidden rounded-lg border p-6">
<div className="rounded-lg border p-6">
<div className="flex flex-col items-center space-y-4">
<div className="h-16 w-16 relative">
<Image
src={resolvedTheme === 'dark' ? "/images/expo-logo-dark.svg" : "/images/expo-logo.svg"}
alt="Expo"
fill
className="object-contain"
/>
<div className="h-16 w-16 bg-muted rounded"></div>
<div className="text-center space-y-2">
<div className="h-6 bg-muted rounded-md w-32"></div>
<div className="h-4 bg-muted rounded-md w-40"></div>
</div>
<div className="text-center">
<h3 className="font-bold text-xl">Expo (Recommended)</h3>
<p className="text-sm text-muted-foreground mt-1">
Quick setup with better developer experience
</p>
</div>
</div>
<div className="rounded-lg border p-6 opacity-50">
<div className="flex flex-col items-center space-y-4">
<div className="h-16 w-16 bg-muted rounded"></div>
<div className="text-center space-y-2">
<div className="h-6 bg-muted rounded-md w-32"></div>
<div className="h-4 bg-muted rounded-md w-40"></div>
</div>
</div>
</div>
</div>

{/* Installation steps skeleton */}
<div className="space-y-8">
<div className="space-y-4">
<div className="h-8 bg-muted rounded-md w-1/3"></div>
<div className="h-5 bg-muted rounded-md w-full"></div>
<div className="h-5 bg-muted rounded-md w-3/4"></div>
</div>

{/* Multiple step skeletons */}
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="space-y-4">
<div className="h-6 bg-muted rounded-md w-1/4"></div>
<div className="h-4 bg-muted rounded-md w-full"></div>
<div className="h-32 bg-muted rounded-md"></div>
</div>
))}
</div>
</div>
);
</div>
);
};

export default function InstallationPage() {
const [selectedPlatform, setSelectedPlatform] = React.useState("expo");
const { resolvedTheme } = useTheme();
const [mounted, setMounted] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(true);

React.useEffect(() => {
const loadResources = async () => {
setIsLoading(true);

// Simulate loading time for theme and resources
await new Promise(resolve => setTimeout(resolve, 800));

setMounted(true);
setIsLoading(false);
};

loadResources();
}, []);

if (isLoading || !mounted) {
return <InstallationPageSkeleton />;
}

return (
Expand Down Expand Up @@ -136,7 +183,7 @@ export default function InstallationPage() {
<div className="mt-8 space-y-12">
<div className="space-y-4">
<h3 className="text-xl font-semibold">1. Create Expo Project</h3>
<InstallationTabs command="create-expo-app my-app --template default" />
<InstallationTabs command="create-expo-app my-app" />
</div>

<div className="space-y-4">
Expand Down Expand Up @@ -250,14 +297,14 @@ module.exports = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">4. Create theme File</h3>
<h3 className="text-xl font-semibold mt-8">4. Create Theme File</h3>
<p className="text-sm text-muted-foreground mb-4">
Create theme.ts in /lib directory:
Create /lib directory and create theme.ts in it:
</p>
<CodeBlock
language="css"
language="typescript"
collapsible
title="theme.ts"
title="lib/theme.ts"
code={`import { vars } from "nativewind";

export const themes = {
Expand Down Expand Up @@ -353,7 +400,85 @@ export const themes = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">5. Create global.css</h3>
<h3 className="text-xl font-semibold mt-8">5. Create Theme Provider</h3>
<p className="text-sm text-muted-foreground mb-4">
Create the theme provider in lib/theme-context.tsx:
</p>
<CodeBlock
language="typescript"
collapsible
title="lib/theme-context.tsx"
code={`import { useColorScheme as useNativewindColorScheme } from 'nativewind';
import React, { createContext, useContext, useEffect, useState } from 'react';
import { useColorScheme as useNativeColorScheme } from 'react-native';
import { themes } from './theme';

type ThemeType = 'light' | 'dark';

interface ThemeContextType {
theme: ThemeType;
setTheme: (theme: ThemeType) => void;
activeTheme: any;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export function ThemeProvider({
children,
defaultTheme = 'system'
}: {
children: React.ReactNode;
defaultTheme?: 'light' | 'dark' | 'system';
}) {
const systemColorScheme = useNativeColorScheme() as ThemeType || 'light';
const [theme, setTheme] = useState<ThemeType>(
defaultTheme === 'system' ? systemColorScheme : defaultTheme as ThemeType
);
const { setColorScheme } = useNativewindColorScheme();

useEffect(() => {
setColorScheme(theme);
}, [theme, setColorScheme]);

const activeTheme = themes[theme];

return (
<ThemeContext.Provider value={{ theme, setTheme, activeTheme }}>
{children}
</ThemeContext.Provider>
);
}

export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}`}
/>
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">6. Create Utility Functions</h3>
<p className="text-sm text-muted-foreground mb-4">
Create utils.ts in /lib directory for class merging utilities:
</p>
<CodeBlock
language="typescript"
collapsible
title="lib/utils.ts"
code={`import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}`}
/>
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">7. Create global.css</h3>
<p className="text-sm text-muted-foreground mb-4">
Create global.css in /app directory:
</p>
Expand All @@ -368,7 +493,7 @@ export const themes = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">6. Configure TypeScript</h3>
<h3 className="text-xl font-semibold mt-8">8. Configure TypeScript</h3>
<p className="text-sm text-muted-foreground mb-4">
Create a new declaration file for NativeWind types:
</p>
Expand All @@ -381,7 +506,7 @@ export const themes = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">7. Configure TypeScript Paths</h3>
<h3 className="text-xl font-semibold mt-8">9. Configure TypeScript Paths</h3>
<p className="text-sm text-muted-foreground mb-4">
Update your tsconfig.json:
</p>
Expand Down Expand Up @@ -412,7 +537,7 @@ export const themes = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">8. Configure Babel</h3>
<h3 className="text-xl font-semibold mt-8">10. Configure Babel</h3>
<p className="text-sm text-muted-foreground mb-4">
Update or create babel.config.js:
</p>
Expand All @@ -436,7 +561,7 @@ export const themes = {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">9. Configure Metro</h3>
<h3 className="text-xl font-semibold mt-8">11. Configure Metro</h3>
<p className="text-sm text-muted-foreground mb-4">
Create metro.config.js:
</p>
Expand All @@ -452,13 +577,13 @@ const { withNativeWind } = require('nativewind/metro');
const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, {
input: './global.css',
input: './app/global.css',
});`}
/>
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">10. Update App Entry</h3>
<h3 className="text-xl font-semibold mt-8">12. Update App Entry</h3>
<p className="text-sm text-muted-foreground mb-4">
Update _layout.tsx:
</p>
Expand All @@ -467,9 +592,7 @@ module.exports = withNativeWind(config, {
collapsible
title="app/_layout.tsx"
code={`import { View } from 'react-native';
import { useState } from 'react';
import { themes } from "@/lib/theme";
import { ThemeProvider, useTheme } from '@/lib/ThemeProvider';
import { ThemeProvider, useTheme } from '@/lib/theme-context';
import './global.css';

export default function RootLayout() {
Expand All @@ -492,7 +615,7 @@ function AppContent() {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">11. Configure app.json</h3>
<h3 className="text-xl font-semibold mt-8">13. Configure app.json</h3>
<p className="text-sm text-muted-foreground mb-4">
Update app.json:
</p>
Expand All @@ -511,7 +634,7 @@ function AppContent() {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">12. Configure shadcn</h3>
<h3 className="text-xl font-semibold mt-8">14. Configure components.json</h3>
<p className="text-sm text-muted-foreground mb-4">
Create components.json in your project root:
</p>
Expand Down Expand Up @@ -548,51 +671,44 @@ function AppContent() {
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">13. Start Development</h3>
<h3 className="text-xl font-semibold mt-8">14. Start Development</h3>
<InstallationTabs command="expo start" />
</div>

<div className="space-y-4">
<h3 className="text-xl font-semibold mt-8">14. Test Your Setup</h3>
<h3 className="text-xl font-semibold mt-8">15. Test Your Setup</h3>
<p className="text-sm text-muted-foreground mb-4">
Add this code in any of your components to test that everything is working:
</p>
<CodeBlock
language="typescript"
language="tsx"
collapsible
title="app/components/TestComponent.tsx"
code={`import { Button } from '@/components/ui/button';
import { Text } from 'react-native';

// ... rest of your imports ...
title="Test Component"
code={`import { View, Text } from 'react-native';

return (
<Button>
<Text className="text-primary-foreground">Click me</Text>
</Button>
);`}
export default function TestComponent() {
return (
<View className="flex-1 justify-center items-center bg-background">
<Text className="text-2xl font-bold text-foreground">
NativeUI is working! 🎉
</Text>
</View>
);
}`}
/>
</div>
</div>
</div>
</div>
) : (
<div className="rounded-lg border-2 border-muted p-8 text-center">
<h2 className="text-2xl font-bold tracking-tight mb-4">React Native CLI Support</h2>
<p className="text-muted-foreground text-lg leading-7">
Support for React Native CLI is coming soon. We recommend using Expo for now.
<div className="text-center py-12">
<h3 className="text-xl font-semibold mb-2">React Native CLI</h3>
<p className="text-muted-foreground">
Support for React Native CLI is coming soon. Stay tuned!
</p>
</div>
)}
</div>

<div className="mt-12 space-y-4">
<h2 className="text-2xl font-bold tracking-tight">Next Steps</h2>
<p className="text-muted-foreground leading-7">
Now that you have set up your project, you can start adding components from our collection.
Visit the components section to explore available components and learn how to use them.
</p>
</div>
</div>
);
}