Cambios App web
This commit is contained in:
parent
3430ae3cb9
commit
515b09e2f7
@ -15,38 +15,43 @@
|
||||
"format": "biome format --write"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.3.1",
|
||||
"@tanstack/react-query-devtools": "^5.74.11",
|
||||
"@types/dinero.js": "^1.9.4",
|
||||
"@types/node": "^22.15.12",
|
||||
"@types/react": "^19.1.2",
|
||||
"@types/react-dom": "^19.1.3",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vite": "^6.3.5"
|
||||
"@biomejs/biome": "^2.4.11",
|
||||
"@tanstack/react-query-devtools": "^5.98.0",
|
||||
"@tailwindcss/postcss": "^4.1.5",
|
||||
"@types/dinero.js": "^2.0.0",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"typescript": "~6.0.2",
|
||||
"vite": "^8.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@erp/auth": "workspace:*",
|
||||
"@erp/core": "workspace:*",
|
||||
"@erp/customer-invoices": "workspace:*",
|
||||
"@erp/customers": "workspace:*",
|
||||
"@fontsource-variable/geist": "^5.2.8",
|
||||
"@fontsource-variable/geist-mono": "^5.2.7",
|
||||
"@repo/i18next": "workspace:*",
|
||||
"@repo/rdx-ui": "workspace:*",
|
||||
"@repo/shadcn-ui": "workspace:*",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@tanstack/react-query": "^5.90.6",
|
||||
"axios": "^1.14.0",
|
||||
"dinero.js": "^1.9.1",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@tanstack/react-query": "^5.98.0",
|
||||
"axios": "^1.15.0",
|
||||
"dinero.js": "1.9.1",
|
||||
"lucide-react": "^1.8.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-error-boundary": "^6.1.1",
|
||||
"react-hook-form": "^7.72.1",
|
||||
"react-i18next": "^15.0.1",
|
||||
"react-router-dom": "^6.26.0",
|
||||
"react-i18next": "^17.0.2",
|
||||
"react-router-dom": "^7.14.0",
|
||||
"react-secure-storage": "^1.3.2",
|
||||
"sequelize": "^6.37.8",
|
||||
"tailwindcss": "^4.1.10",
|
||||
"tw-animate-css": "^1.2.9",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"vite-plugin-html": "^3.2.2"
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import { AuthProvider, createAuthService } from "@erp/auth/client";
|
||||
import { createAxiosDataSource, createAxiosInstance } from "@erp/core/client";
|
||||
import { DataSourceProvider } from "@erp/core/hooks";
|
||||
import { i18n } from "@repo/i18next";
|
||||
import { LoadingOverlay } from "@repo/rdx-ui/components";
|
||||
import { Toaster, TooltipProvider } from "@repo/shadcn-ui/components";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
@ -13,10 +14,6 @@ import { RouterProvider } from "react-router-dom";
|
||||
import { clearAccessToken, getAccessToken, setAccessToken } from "./lib";
|
||||
import { getAppRouter } from "./routes";
|
||||
|
||||
import "./app.css";
|
||||
|
||||
import { i18n } from "@repo/i18next";
|
||||
|
||||
export const App = () => {
|
||||
DineroFactory.globalLocale = "es-ES";
|
||||
|
||||
@ -56,7 +53,7 @@ export const App = () => {
|
||||
authService: createAuthService(),
|
||||
}}
|
||||
>
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<TooltipProvider>
|
||||
{/* Fallback Route */}
|
||||
<Suspense fallback={<LoadingOverlay />}>
|
||||
<RouterProvider router={appRouter} />
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import secureLocalStorage from "react-secure-storage";
|
||||
import secureLocalStorageImport from "react-secure-storage";
|
||||
|
||||
/**
|
||||
* Servicio para manejar la obtención del token JWT desde el almacenamiento local.
|
||||
* Este archivo puede evolucionar a un AuthService más completo en el futuro.
|
||||
*/
|
||||
|
||||
const secureLocalStorage = (secureLocalStorageImport as any)?.default ?? secureLocalStorageImport;
|
||||
|
||||
/**
|
||||
* Clave utilizada en el almacenamiento local para el token JWT.
|
||||
*/
|
||||
@ -17,7 +19,7 @@ const TOKEN_STORAGE_KEY = "factuges.auth";
|
||||
* @returns El token como string, o null si no está disponible.
|
||||
*/
|
||||
export const getAccessToken = (): string | null => {
|
||||
const authInfo = secureLocalStorage.getItem(TOKEN_STORAGE_KEY) as { token?: string } | null;
|
||||
const authInfo = secureLocalStorage?.getItem?.(TOKEN_STORAGE_KEY) as { token?: string } | null;
|
||||
return typeof authInfo?.token === "string" ? authInfo.token : null;
|
||||
};
|
||||
|
||||
@ -27,14 +29,12 @@ export const getAccessToken = (): string | null => {
|
||||
* @params El token como string.
|
||||
*/
|
||||
export const setAccessToken = (token: string): void => {
|
||||
secureLocalStorage.setItem(TOKEN_STORAGE_KEY, token);
|
||||
secureLocalStorage?.setItem?.(TOKEN_STORAGE_KEY, token);
|
||||
};
|
||||
|
||||
setAccessToken;
|
||||
|
||||
/**
|
||||
* Limpia el token JWT del almacenamiento local.
|
||||
*/
|
||||
export const clearAccessToken = (): void => {
|
||||
secureLocalStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
secureLocalStorage?.removeItem?.(TOKEN_STORAGE_KEY);
|
||||
};
|
||||
|
||||
295
apps/web/src/pages/shadcn-ui-page.tsx
Normal file
295
apps/web/src/pages/shadcn-ui-page.tsx
Normal file
@ -0,0 +1,295 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
Badge,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
Checkbox,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
Field,
|
||||
FieldGroup,
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
Item,
|
||||
ItemActions,
|
||||
ItemContent,
|
||||
ItemDescription,
|
||||
ItemTitle,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Slider,
|
||||
Switch,
|
||||
Textarea,
|
||||
} from "@repo/shadcn-ui/components";
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowRightIcon,
|
||||
CheckIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronRightIcon,
|
||||
ChevronUpIcon,
|
||||
CircleAlertIcon,
|
||||
CopyIcon,
|
||||
Loader2Icon,
|
||||
MinusIcon,
|
||||
MoreHorizontalIcon,
|
||||
PlusIcon,
|
||||
SearchIcon,
|
||||
SettingsIcon,
|
||||
ShareIcon,
|
||||
ShoppingBagIcon,
|
||||
TrashIcon,
|
||||
} from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
export default function ShadcnShowcasePage() {
|
||||
const [sliderValue, setSliderValue] = React.useState<number[]>([500]);
|
||||
const handleSliderValueChange = React.useCallback((value: number[]) => {
|
||||
setSliderValue(value);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen w-full flex-col items-center justify-center bg-muted p-4 sm:p-6 lg:p-12 dark:bg-background">
|
||||
<div className="grid max-w-3xl gap-4 sm:grid-cols-2">
|
||||
<div className="flex flex-col gap-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Style Overview</CardTitle>
|
||||
<CardDescription className="line-clamp-2">
|
||||
Designers love packing quirky glyphs into test phrases. This is a preview of the
|
||||
typography styles.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-6 gap-3">
|
||||
{[
|
||||
"--background",
|
||||
"--foreground",
|
||||
"--primary",
|
||||
"--secondary",
|
||||
"--muted",
|
||||
"--accent",
|
||||
"--border",
|
||||
"--chart-1",
|
||||
"--chart-2",
|
||||
"--chart-3",
|
||||
"--chart-4",
|
||||
"--chart-5",
|
||||
].map((variant) => (
|
||||
<div className="flex flex-col flex-wrap items-center gap-2" key={variant}>
|
||||
<div
|
||||
className="relative aspect-square w-full rounded-lg bg-(--color) after:absolute after:inset-0 after:rounded-lg after:border after:border-border after:mix-blend-darken dark:after:mix-blend-lighten"
|
||||
style={
|
||||
{
|
||||
"--color": `var(${variant})`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
/>
|
||||
<div className="hidden max-w-14 truncate font-mono text-[0.60rem] md:block">
|
||||
{variant}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-8 place-items-center gap-4">
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<CopyIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<CircleAlertIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<TrashIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ShareIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ShoppingBagIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<MoreHorizontalIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<Loader2Icon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<PlusIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<MinusIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ArrowLeftIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ArrowRightIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<CheckIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ChevronDownIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<ChevronRightIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<SearchIcon />
|
||||
</Card>
|
||||
<Card className="flex size-8 items-center justify-center rounded-md p-0 ring ring-border *:[svg]:size-4">
|
||||
<SettingsIcon />
|
||||
</Card>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<Card className="w-full">
|
||||
<CardContent className="flex flex-col gap-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button>Button</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="outline">Outline</Button>
|
||||
<Button variant="ghost">Ghost</Button>
|
||||
</div>
|
||||
<Item variant="outline">
|
||||
<ItemContent>
|
||||
<ItemTitle>Two-factor authentication</ItemTitle>
|
||||
<ItemDescription className="text-pretty xl:hidden 2xl:block">
|
||||
Verify via email or phone number.
|
||||
</ItemDescription>
|
||||
</ItemContent>
|
||||
<ItemActions className="hidden md:flex">
|
||||
<Button size="sm" variant="secondary">
|
||||
Enable
|
||||
</Button>
|
||||
</ItemActions>
|
||||
</Item>
|
||||
</div>
|
||||
<Slider
|
||||
aria-label="Slider"
|
||||
className="flex-1"
|
||||
max={1000}
|
||||
min={0}
|
||||
onValueChange={handleSliderValueChange}
|
||||
step={10}
|
||||
value={sliderValue}
|
||||
/>
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<InputGroup>
|
||||
<InputGroupInput placeholder="Name" />
|
||||
<InputGroupAddon align="inline-end">
|
||||
<InputGroupText>
|
||||
<SearchIcon />
|
||||
</InputGroupText>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
</Field>
|
||||
<Field className="flex-1">
|
||||
<Textarea className="resize-none" placeholder="Message" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex gap-2">
|
||||
<Badge>Badge</Badge>
|
||||
<Badge variant="secondary">Secondary</Badge>
|
||||
<Badge variant="outline">Outline</Badge>
|
||||
</div>
|
||||
<RadioGroup className="ml-auto flex w-fit gap-3" defaultValue="apple">
|
||||
<RadioGroupItem value="apple" />
|
||||
<RadioGroupItem value="banana" />
|
||||
</RadioGroup>
|
||||
<div className="flex gap-3">
|
||||
<Checkbox defaultChecked />
|
||||
<Checkbox />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="outline">
|
||||
<span className="hidden md:block">Alert Dialog</span>
|
||||
<span className="block md:hidden">Dialog</span>
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent size="sm">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Allow accessory to connect?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Do you want to allow the USB accessory to connect to this device and your
|
||||
data?
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Don't allow</AlertDialogCancel>
|
||||
<AlertDialogAction>Allow</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
<ButtonGroup>
|
||||
<Button variant="outline">Button Group</Button>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="icon" variant="outline">
|
||||
<ChevronUpIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-fit" side="top">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>Quick Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Mute Conversation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Mark as Read</DropdownMenuItem>
|
||||
<DropdownMenuItem>Block User</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>Conversation</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Share Conversation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Copy Conversation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Report Conversation</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem variant="destructive">
|
||||
Delete Conversation
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</ButtonGroup>
|
||||
<Switch className="ml-auto" defaultChecked />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
608
apps/web/src/pages/tailwindcss-page.tsx
Normal file
608
apps/web/src/pages/tailwindcss-page.tsx
Normal file
@ -0,0 +1,608 @@
|
||||
// src/assets/tailwindcss-page.tsx
|
||||
|
||||
const textSizes = [
|
||||
"text-xs",
|
||||
"text-sm",
|
||||
"text-base",
|
||||
"text-lg",
|
||||
"text-xl",
|
||||
"text-2xl",
|
||||
"text-3xl",
|
||||
"text-4xl",
|
||||
"text-5xl",
|
||||
] as const;
|
||||
|
||||
const fontFamilies = ["font-sans", "font-serif", "font-mono"] as const;
|
||||
|
||||
const fontWeights = [
|
||||
"font-thin",
|
||||
"font-extralight",
|
||||
"font-light",
|
||||
"font-normal",
|
||||
"font-medium",
|
||||
"font-semibold",
|
||||
"font-bold",
|
||||
"font-extrabold",
|
||||
"font-black",
|
||||
] as const;
|
||||
|
||||
const tracking = [
|
||||
"tracking-tighter",
|
||||
"tracking-tight",
|
||||
"tracking-normal",
|
||||
"tracking-wide",
|
||||
"tracking-wider",
|
||||
"tracking-widest",
|
||||
] as const;
|
||||
|
||||
const leading = [
|
||||
"leading-none",
|
||||
"leading-tight",
|
||||
"leading-snug",
|
||||
"leading-normal",
|
||||
"leading-relaxed",
|
||||
"leading-loose",
|
||||
] as const;
|
||||
|
||||
const palette = [
|
||||
"slate",
|
||||
"gray",
|
||||
"zinc",
|
||||
"neutral",
|
||||
"stone",
|
||||
"red",
|
||||
"orange",
|
||||
"amber",
|
||||
"yellow",
|
||||
"lime",
|
||||
"green",
|
||||
"emerald",
|
||||
"teal",
|
||||
"cyan",
|
||||
"sky",
|
||||
"blue",
|
||||
"indigo",
|
||||
"violet",
|
||||
"purple",
|
||||
"fuchsia",
|
||||
"pink",
|
||||
"rose",
|
||||
] as const;
|
||||
|
||||
const shades = [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"800",
|
||||
"900",
|
||||
"950",
|
||||
] as const;
|
||||
|
||||
const colorClasses = {
|
||||
slate: {
|
||||
"50": "bg-slate-50 text-black",
|
||||
"100": "bg-slate-100 text-black",
|
||||
"200": "bg-slate-200 text-black",
|
||||
"300": "bg-slate-300 text-black",
|
||||
"400": "bg-slate-400 text-black",
|
||||
"500": "bg-slate-500 text-white",
|
||||
"600": "bg-slate-600 text-white",
|
||||
"700": "bg-slate-700 text-white",
|
||||
"800": "bg-slate-800 text-white",
|
||||
"900": "bg-slate-900 text-white",
|
||||
"950": "bg-slate-950 text-white",
|
||||
},
|
||||
gray: {
|
||||
"50": "bg-gray-50 text-black",
|
||||
"100": "bg-gray-100 text-black",
|
||||
"200": "bg-gray-200 text-black",
|
||||
"300": "bg-gray-300 text-black",
|
||||
"400": "bg-gray-400 text-black",
|
||||
"500": "bg-gray-500 text-white",
|
||||
"600": "bg-gray-600 text-white",
|
||||
"700": "bg-gray-700 text-white",
|
||||
"800": "bg-gray-800 text-white",
|
||||
"900": "bg-gray-900 text-white",
|
||||
"950": "bg-gray-950 text-white",
|
||||
},
|
||||
zinc: {
|
||||
"50": "bg-zinc-50 text-black",
|
||||
"100": "bg-zinc-100 text-black",
|
||||
"200": "bg-zinc-200 text-black",
|
||||
"300": "bg-zinc-300 text-black",
|
||||
"400": "bg-zinc-400 text-black",
|
||||
"500": "bg-zinc-500 text-white",
|
||||
"600": "bg-zinc-600 text-white",
|
||||
"700": "bg-zinc-700 text-white",
|
||||
"800": "bg-zinc-800 text-white",
|
||||
"900": "bg-zinc-900 text-white",
|
||||
"950": "bg-zinc-950 text-white",
|
||||
},
|
||||
neutral: {
|
||||
"50": "bg-neutral-50 text-black",
|
||||
"100": "bg-neutral-100 text-black",
|
||||
"200": "bg-neutral-200 text-black",
|
||||
"300": "bg-neutral-300 text-black",
|
||||
"400": "bg-neutral-400 text-black",
|
||||
"500": "bg-neutral-500 text-white",
|
||||
"600": "bg-neutral-600 text-white",
|
||||
"700": "bg-neutral-700 text-white",
|
||||
"800": "bg-neutral-800 text-white",
|
||||
"900": "bg-neutral-900 text-white",
|
||||
"950": "bg-neutral-950 text-white",
|
||||
},
|
||||
stone: {
|
||||
"50": "bg-stone-50 text-black",
|
||||
"100": "bg-stone-100 text-black",
|
||||
"200": "bg-stone-200 text-black",
|
||||
"300": "bg-stone-300 text-black",
|
||||
"400": "bg-stone-400 text-black",
|
||||
"500": "bg-stone-500 text-white",
|
||||
"600": "bg-stone-600 text-white",
|
||||
"700": "bg-stone-700 text-white",
|
||||
"800": "bg-stone-800 text-white",
|
||||
"900": "bg-stone-900 text-white",
|
||||
"950": "bg-stone-950 text-white",
|
||||
},
|
||||
red: {
|
||||
"50": "bg-red-50 text-black",
|
||||
"100": "bg-red-100 text-black",
|
||||
"200": "bg-red-200 text-black",
|
||||
"300": "bg-red-300 text-black",
|
||||
"400": "bg-red-400 text-black",
|
||||
"500": "bg-red-500 text-white",
|
||||
"600": "bg-red-600 text-white",
|
||||
"700": "bg-red-700 text-white",
|
||||
"800": "bg-red-800 text-white",
|
||||
"900": "bg-red-900 text-white",
|
||||
"950": "bg-red-950 text-white",
|
||||
},
|
||||
orange: {
|
||||
"50": "bg-orange-50 text-black",
|
||||
"100": "bg-orange-100 text-black",
|
||||
"200": "bg-orange-200 text-black",
|
||||
"300": "bg-orange-300 text-black",
|
||||
"400": "bg-orange-400 text-black",
|
||||
"500": "bg-orange-500 text-white",
|
||||
"600": "bg-orange-600 text-white",
|
||||
"700": "bg-orange-700 text-white",
|
||||
"800": "bg-orange-800 text-white",
|
||||
"900": "bg-orange-900 text-white",
|
||||
"950": "bg-orange-950 text-white",
|
||||
},
|
||||
amber: {
|
||||
"50": "bg-amber-50 text-black",
|
||||
"100": "bg-amber-100 text-black",
|
||||
"200": "bg-amber-200 text-black",
|
||||
"300": "bg-amber-300 text-black",
|
||||
"400": "bg-amber-400 text-black",
|
||||
"500": "bg-amber-500 text-black",
|
||||
"600": "bg-amber-600 text-white",
|
||||
"700": "bg-amber-700 text-white",
|
||||
"800": "bg-amber-800 text-white",
|
||||
"900": "bg-amber-900 text-white",
|
||||
"950": "bg-amber-950 text-white",
|
||||
},
|
||||
yellow: {
|
||||
"50": "bg-yellow-50 text-black",
|
||||
"100": "bg-yellow-100 text-black",
|
||||
"200": "bg-yellow-200 text-black",
|
||||
"300": "bg-yellow-300 text-black",
|
||||
"400": "bg-yellow-400 text-black",
|
||||
"500": "bg-yellow-500 text-black",
|
||||
"600": "bg-yellow-600 text-black",
|
||||
"700": "bg-yellow-700 text-white",
|
||||
"800": "bg-yellow-800 text-white",
|
||||
"900": "bg-yellow-900 text-white",
|
||||
"950": "bg-yellow-950 text-white",
|
||||
},
|
||||
lime: {
|
||||
"50": "bg-lime-50 text-black",
|
||||
"100": "bg-lime-100 text-black",
|
||||
"200": "bg-lime-200 text-black",
|
||||
"300": "bg-lime-300 text-black",
|
||||
"400": "bg-lime-400 text-black",
|
||||
"500": "bg-lime-500 text-black",
|
||||
"600": "bg-lime-600 text-black",
|
||||
"700": "bg-lime-700 text-white",
|
||||
"800": "bg-lime-800 text-white",
|
||||
"900": "bg-lime-900 text-white",
|
||||
"950": "bg-lime-950 text-white",
|
||||
},
|
||||
green: {
|
||||
"50": "bg-green-50 text-black",
|
||||
"100": "bg-green-100 text-black",
|
||||
"200": "bg-green-200 text-black",
|
||||
"300": "bg-green-300 text-black",
|
||||
"400": "bg-green-400 text-black",
|
||||
"500": "bg-green-500 text-white",
|
||||
"600": "bg-green-600 text-white",
|
||||
"700": "bg-green-700 text-white",
|
||||
"800": "bg-green-800 text-white",
|
||||
"900": "bg-green-900 text-white",
|
||||
"950": "bg-green-950 text-white",
|
||||
},
|
||||
emerald: {
|
||||
"50": "bg-emerald-50 text-black",
|
||||
"100": "bg-emerald-100 text-black",
|
||||
"200": "bg-emerald-200 text-black",
|
||||
"300": "bg-emerald-300 text-black",
|
||||
"400": "bg-emerald-400 text-black",
|
||||
"500": "bg-emerald-500 text-white",
|
||||
"600": "bg-emerald-600 text-white",
|
||||
"700": "bg-emerald-700 text-white",
|
||||
"800": "bg-emerald-800 text-white",
|
||||
"900": "bg-emerald-900 text-white",
|
||||
"950": "bg-emerald-950 text-white",
|
||||
},
|
||||
teal: {
|
||||
"50": "bg-teal-50 text-black",
|
||||
"100": "bg-teal-100 text-black",
|
||||
"200": "bg-teal-200 text-black",
|
||||
"300": "bg-teal-300 text-black",
|
||||
"400": "bg-teal-400 text-black",
|
||||
"500": "bg-teal-500 text-white",
|
||||
"600": "bg-teal-600 text-white",
|
||||
"700": "bg-teal-700 text-white",
|
||||
"800": "bg-teal-800 text-white",
|
||||
"900": "bg-teal-900 text-white",
|
||||
"950": "bg-teal-950 text-white",
|
||||
},
|
||||
cyan: {
|
||||
"50": "bg-cyan-50 text-black",
|
||||
"100": "bg-cyan-100 text-black",
|
||||
"200": "bg-cyan-200 text-black",
|
||||
"300": "bg-cyan-300 text-black",
|
||||
"400": "bg-cyan-400 text-black",
|
||||
"500": "bg-cyan-500 text-black",
|
||||
"600": "bg-cyan-600 text-black",
|
||||
"700": "bg-cyan-700 text-white",
|
||||
"800": "bg-cyan-800 text-white",
|
||||
"900": "bg-cyan-900 text-white",
|
||||
"950": "bg-cyan-950 text-white",
|
||||
},
|
||||
sky: {
|
||||
"50": "bg-sky-50 text-black",
|
||||
"100": "bg-sky-100 text-black",
|
||||
"200": "bg-sky-200 text-black",
|
||||
"300": "bg-sky-300 text-black",
|
||||
"400": "bg-sky-400 text-black",
|
||||
"500": "bg-sky-500 text-white",
|
||||
"600": "bg-sky-600 text-white",
|
||||
"700": "bg-sky-700 text-white",
|
||||
"800": "bg-sky-800 text-white",
|
||||
"900": "bg-sky-900 text-white",
|
||||
"950": "bg-sky-950 text-white",
|
||||
},
|
||||
blue: {
|
||||
"50": "bg-blue-50 text-black",
|
||||
"100": "bg-blue-100 text-black",
|
||||
"200": "bg-blue-200 text-black",
|
||||
"300": "bg-blue-300 text-black",
|
||||
"400": "bg-blue-400 text-black",
|
||||
"500": "bg-blue-500 text-white",
|
||||
"600": "bg-blue-600 text-white",
|
||||
"700": "bg-blue-700 text-white",
|
||||
"800": "bg-blue-800 text-white",
|
||||
"900": "bg-blue-900 text-white",
|
||||
"950": "bg-blue-950 text-white",
|
||||
},
|
||||
indigo: {
|
||||
"50": "bg-indigo-50 text-black",
|
||||
"100": "bg-indigo-100 text-black",
|
||||
"200": "bg-indigo-200 text-black",
|
||||
"300": "bg-indigo-300 text-black",
|
||||
"400": "bg-indigo-400 text-black",
|
||||
"500": "bg-indigo-500 text-white",
|
||||
"600": "bg-indigo-600 text-white",
|
||||
"700": "bg-indigo-700 text-white",
|
||||
"800": "bg-indigo-800 text-white",
|
||||
"900": "bg-indigo-900 text-white",
|
||||
"950": "bg-indigo-950 text-white",
|
||||
},
|
||||
violet: {
|
||||
"50": "bg-violet-50 text-black",
|
||||
"100": "bg-violet-100 text-black",
|
||||
"200": "bg-violet-200 text-black",
|
||||
"300": "bg-violet-300 text-black",
|
||||
"400": "bg-violet-400 text-black",
|
||||
"500": "bg-violet-500 text-white",
|
||||
"600": "bg-violet-600 text-white",
|
||||
"700": "bg-violet-700 text-white",
|
||||
"800": "bg-violet-800 text-white",
|
||||
"900": "bg-violet-900 text-white",
|
||||
"950": "bg-violet-950 text-white",
|
||||
},
|
||||
purple: {
|
||||
"50": "bg-purple-50 text-black",
|
||||
"100": "bg-purple-100 text-black",
|
||||
"200": "bg-purple-200 text-black",
|
||||
"300": "bg-purple-300 text-black",
|
||||
"400": "bg-purple-400 text-black",
|
||||
"500": "bg-purple-500 text-white",
|
||||
"600": "bg-purple-600 text-white",
|
||||
"700": "bg-purple-700 text-white",
|
||||
"800": "bg-purple-800 text-white",
|
||||
"900": "bg-purple-900 text-white",
|
||||
"950": "bg-purple-950 text-white",
|
||||
},
|
||||
fuchsia: {
|
||||
"50": "bg-fuchsia-50 text-black",
|
||||
"100": "bg-fuchsia-100 text-black",
|
||||
"200": "bg-fuchsia-200 text-black",
|
||||
"300": "bg-fuchsia-300 text-black",
|
||||
"400": "bg-fuchsia-400 text-black",
|
||||
"500": "bg-fuchsia-500 text-white",
|
||||
"600": "bg-fuchsia-600 text-white",
|
||||
"700": "bg-fuchsia-700 text-white",
|
||||
"800": "bg-fuchsia-800 text-white",
|
||||
"900": "bg-fuchsia-900 text-white",
|
||||
"950": "bg-fuchsia-950 text-white",
|
||||
},
|
||||
pink: {
|
||||
"50": "bg-pink-50 text-black",
|
||||
"100": "bg-pink-100 text-black",
|
||||
"200": "bg-pink-200 text-black",
|
||||
"300": "bg-pink-300 text-black",
|
||||
"400": "bg-pink-400 text-black",
|
||||
"500": "bg-pink-500 text-white",
|
||||
"600": "bg-pink-600 text-white",
|
||||
"700": "bg-pink-700 text-white",
|
||||
"800": "bg-pink-800 text-white",
|
||||
"900": "bg-pink-900 text-white",
|
||||
"950": "bg-pink-950 text-white",
|
||||
},
|
||||
rose: {
|
||||
"50": "bg-rose-50 text-black",
|
||||
"100": "bg-rose-100 text-black",
|
||||
"200": "bg-rose-200 text-black",
|
||||
"300": "bg-rose-300 text-black",
|
||||
"400": "bg-rose-400 text-black",
|
||||
"500": "bg-rose-500 text-white",
|
||||
"600": "bg-rose-600 text-white",
|
||||
"700": "bg-rose-700 text-white",
|
||||
"800": "bg-rose-800 text-white",
|
||||
"900": "bg-rose-900 text-white",
|
||||
"950": "bg-rose-950 text-white",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export default function TailwindV4ShowcasePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<div className="container mx-auto flex max-w-7xl flex-col gap-10 px-6 py-10">
|
||||
<header className="space-y-3">
|
||||
<p className="text-sm uppercase tracking-widest text-muted-foreground">Tailwind CSS v4</p>
|
||||
<h1 className="text-4xl font-bold tracking-tight">Typography + Colors Showcase</h1>
|
||||
<p className="max-w-3xl text-muted-foreground">
|
||||
Página de prueba para validar escala tipográfica, pesos, tracking, line-height, tokens
|
||||
semánticos, paleta base y estados de color.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Tokens semánticos del tema</div>
|
||||
<div>
|
||||
Estos bloques validan que los tokens del sistema y el theme estén correctamente
|
||||
conectados.
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div className="rounded-xl border bg-background p-4">
|
||||
<p className="font-medium">bg-background</p>
|
||||
<p className="text-sm text-muted-foreground">foreground / muted-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl border bg-card p-4 text-card-foreground">
|
||||
<p className="font-medium">bg-card</p>
|
||||
<p className="text-sm opacity-70">text-card-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl bg-primary p-4 text-primary-foreground">
|
||||
<p className="font-medium">bg-primary</p>
|
||||
<p className="text-sm opacity-80">text-primary-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl bg-secondary p-4 text-secondary-foreground">
|
||||
<p className="font-medium">bg-secondary</p>
|
||||
<p className="text-sm opacity-80">text-secondary-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl bg-muted p-4 text-muted-foreground">
|
||||
<p className="font-medium text-foreground">bg-muted</p>
|
||||
<p className="text-sm">text-muted-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl bg-accent p-4 text-accent-foreground">
|
||||
<p className="font-medium">bg-accent</p>
|
||||
<p className="text-sm opacity-80">text-accent-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl bg-destructive p-4 text-destructive-foreground">
|
||||
<p className="font-medium">bg-destructive</p>
|
||||
<p className="text-sm opacity-80">text-destructive-foreground</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border p-4">
|
||||
<p className="font-medium">border-border</p>
|
||||
<p className="text-sm text-muted-foreground">ring, input, radius, etc.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Escala tipográfica</div>
|
||||
<div>Tamaños de texto del sistema.</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{textSizes.map((cls) => (
|
||||
<div className="rounded-lg border p-4" key={cls}>
|
||||
<p className={`${cls} font-medium`}>
|
||||
{cls} — The quick brown fox jumps over the lazy dog.
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<div>
|
||||
<div>
|
||||
<div>Familias tipográficas</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{fontFamilies.map((cls) => (
|
||||
<div className="rounded-lg border p-4" key={cls}>
|
||||
<p className={`${cls} text-xl`}>{cls} — Sphinx of black quartz, judge my vow.</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Pesos tipográficos</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{fontWeights.map((cls) => (
|
||||
<div className="rounded-lg border p-4" key={cls}>
|
||||
<p className={`${cls} text-lg`}>
|
||||
{cls} — Pack my box with five dozen liquor jugs.
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<div>
|
||||
<div>
|
||||
<div>Tracking</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{tracking.map((cls) => (
|
||||
<div className="rounded-lg border p-4" key={cls}>
|
||||
<p className={`${cls} text-lg uppercase`}>{cls} — Tailwind v4</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Leading</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{leading.map((cls) => (
|
||||
<div className="rounded-lg border p-4" key={cls}>
|
||||
<p className={`${cls} max-w-xl`}>
|
||||
<span className="font-medium">{cls}</span> — Lorem ipsum dolor sit amet,
|
||||
consectetur adipisicing elit. Provident sapiente similique fugit quos tempora
|
||||
commodi animi minima porro quas.
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Decoración y estilos de texto</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="underline decoration-2">underline decoration-2</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="line-through">line-through</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="italic">italic</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="not-italic">not-italic</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="uppercase">uppercase</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="lowercase">LOWERCASE</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="capitalize">capitalize every first letter</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="truncate">
|
||||
truncate — este texto es deliberadamente muy largo para validar la elipsis en una
|
||||
sola línea dentro del layout
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-lg border p-4">
|
||||
<p className="text-balance text-lg">
|
||||
text-balance para titulares y bloques con wrapping más estable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<section className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Paleta completa</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Cada bloque usa clases explícitas, para que Tailwind pueda detectarlas al compilar.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{palette.map((color) => (
|
||||
<div key={color}>
|
||||
<div>
|
||||
<div className="capitalize">{color}</div>
|
||||
<div>Shades 50 → 950</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-11">
|
||||
{shades.map((shade) => (
|
||||
<div
|
||||
className={`rounded-lg border p-3 ${colorClasses[color][shade]}`}
|
||||
key={`${color}-${shade}`}
|
||||
>
|
||||
<p className="text-sm font-semibold">
|
||||
{color}-{shade}
|
||||
</p>
|
||||
<p className="text-xs opacity-80">bg / preview</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>Estados interactivos</div>
|
||||
<div>Hover, focus, ring y transiciones básicas.</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<button className="rounded-lg border bg-background px-4 py-3 text-left transition hover:bg-accent hover:text-accent-foreground focus:outline-none focus:ring-2 focus:ring-ring">
|
||||
Hover + focus ring
|
||||
</button>
|
||||
<button className="rounded-lg bg-primary px-4 py-3 text-left text-primary-foreground transition hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-ring">
|
||||
Primary action
|
||||
</button>
|
||||
<button className="rounded-lg bg-secondary px-4 py-3 text-left text-secondary-foreground transition hover:bg-secondary/80 focus:outline-none focus:ring-2 focus:ring-ring">
|
||||
Secondary action
|
||||
</button>
|
||||
<button className="rounded-lg border border-destructive/30 bg-destructive/10 px-4 py-3 text-left text-destructive transition hover:bg-destructive hover:text-destructive-foreground focus:outline-none focus:ring-2 focus:ring-ring">
|
||||
Destructive action
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -3,6 +3,8 @@ import { AppLayout } from "@repo/rdx-ui/components";
|
||||
import { Navigate, Route, createBrowserRouter, createRoutesFromElements } from "react-router-dom";
|
||||
|
||||
import { ModuleRoutes } from "@/components/module-routes";
|
||||
import ShadcnShowcasePage from "@/pages/shadcn-ui-page";
|
||||
import TailwindV4ShowcasePage from "@/pages/tailwindcss-page";
|
||||
|
||||
import { ErrorPage, LoginForm } from "../pages";
|
||||
import { modules } from "../register-modules"; // Aquí ca
|
||||
@ -48,6 +50,10 @@ export const getAppRouter = () => {
|
||||
{/* Dynamic Module Routes */}
|
||||
<Route element={<ModuleRoutes modules={grouped.app} params={params} />} path="*" />
|
||||
|
||||
{/* Test */}
|
||||
<Route element={<ShadcnShowcasePage />} path="/shadcnui" />
|
||||
<Route element={<TailwindV4ShowcasePage />} path="/tailwindcss4" />
|
||||
|
||||
{/* Main Layout */}
|
||||
<Route element={<ErrorPage />} path="/dashboard" />
|
||||
<Route element={<ErrorPage />} path="/settings" />
|
||||
|
||||
@ -6,7 +6,10 @@ import { defineConfig } from "vite";
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
build: {
|
||||
sourcemap: true,
|
||||
sourcemap: true
|
||||
},
|
||||
define: {
|
||||
"process.env": {}
|
||||
},
|
||||
plugins: [react(), tailwindcss()],
|
||||
resolve: {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user