@axzydev/axzy_ui_system 1.4.8 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -11
- package/dist/index.cjs +1826 -1351
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +115 -14
- package/dist/index.d.ts +115 -14
- package/dist/index.js +1481 -1010
- package/dist/index.js.map +1 -1
- package/dist/layered.css +1 -1
- package/package.json +3 -16
- package/src/App.tsx +90 -73
- package/src/components/atoms/badget/badget.tsx +23 -5
- package/src/components/atoms/chip/chip.tsx +3 -1
- package/src/components/atoms/image/image.tsx +3 -1
- package/src/components/atoms/input/input.tsx +8 -5
- package/src/components/atoms/loader/loader.tsx +3 -1
- package/src/components/atoms/slide/slide.props.ts +12 -0
- package/src/components/atoms/slide/slide.tsx +3 -0
- package/src/components/molecules/alert/alert.tsx +3 -1
- package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
- package/src/components/molecules/calendar/calendar.tsx +9 -6
- package/src/components/molecules/card/card.tsx +5 -2
- package/src/components/molecules/chip-input/chip-input.tsx +9 -7
- package/src/components/molecules/date-picker/datePicker.tsx +9 -9
- package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
- package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
- package/src/components/molecules/field/field.tsx +3 -1
- package/src/components/molecules/form-header/form-header.tsx +3 -1
- package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
- package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
- package/src/components/molecules/masked-input/masked-input.tsx +3 -1
- package/src/components/molecules/multi-select/multi-select.tsx +12 -9
- package/src/components/molecules/pagination/pagination.tsx +11 -5
- package/src/components/molecules/search-select/search-select.tsx +11 -9
- package/src/components/molecules/select/select.tsx +6 -4
- package/src/components/molecules/stepper/stepper.tsx +6 -4
- package/src/components/molecules/table/table.tsx +30 -28
- package/src/components/molecules/time-picker/timePicker.tsx +8 -6
- package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
- package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
- package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
- package/src/components/organisms/data-table/dataTable.tsx +31 -25
- package/src/components/organisms/dialog/dialog.tsx +3 -0
- package/src/components/organisms/drawer/drawer.tsx +3 -0
- package/src/components/organisms/dropfile/dropfile.tsx +19 -17
- package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
- package/src/components/organisms/navbar/navbar.tsx +4 -2
- package/src/components/organisms/page-header/page-header.tsx +3 -1
- package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
- package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
- package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
- package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
- package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
- package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
- package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
- package/src/components/organisms/searchTable/searchTable.tsx +4 -2
- package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
- package/src/components/organisms/sidebar/sidebar.tsx +9 -4
- package/src/components/organisms/toast/toast.tsx +3 -1
- package/src/components/organisms/topbar/topbar.tsx +4 -2
- package/src/components/templates/page/page.props.ts +4 -4
- package/src/components/templates/page/page.tsx +6 -4
- package/src/components/theme-provider/themeProvider.tsx +28 -17
- package/src/dev.css +77 -2
- package/src/global.d.ts +10 -0
- package/src/i18n/context.ts +9 -0
- package/src/i18n/index.ts +22 -0
- package/src/i18n/locales/en.ts +163 -0
- package/src/i18n/locales/es.ts +165 -0
- package/src/i18n/provider.tsx +44 -0
- package/src/i18n/translator.ts +82 -0
- package/src/i18n/types.ts +54 -0
- package/src/i18n/useITTranslation.ts +20 -0
- package/src/index.css +0 -1
- package/src/index.ts +7 -1
- package/src/sandbox/LandingShowcase.tsx +224 -580
- package/src/sandbox/NotFoundShowcase.tsx +51 -36
- package/src/sandbox/TopbarSearch.tsx +6 -4
- package/src/sandbox/controls.tsx +180 -0
- package/src/sandbox/i18n.ts +1929 -0
- package/src/sandbox/icons.tsx +25 -0
- package/src/sandbox/locale.tsx +72 -0
- package/src/sandbox/ui.tsx +377 -0
- package/src/sandbox/useHashRoute.ts +46 -10
- package/src/showcases/DataShowcases.tsx +103 -87
- package/src/showcases/FeedbackShowcases.tsx +37 -30
- package/src/showcases/FormShowcases.tsx +302 -214
- package/src/showcases/GettingStartedShowcase.tsx +151 -145
- package/src/showcases/HelpShowcase.tsx +126 -128
- package/src/showcases/HomeShowcase.tsx +678 -482
- package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
- package/src/showcases/NavigationShowcases.tsx +45 -37
- package/src/showcases/PageShowcases.tsx +171 -152
- package/src/showcases/ProductoDetalle.tsx +272 -129
- package/src/showcases/ShowcaseLayout.tsx +270 -216
- package/src/showcases/SizesShowcase.tsx +123 -64
- package/src/showcases/StructureShowcases.tsx +157 -131
- package/src/showcases/portfolioUi.tsx +153 -0
- package/src/showcases/techIcons.ts +3 -0
- package/src/utils/table.utils.ts +10 -2
- package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
- package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
- package/src/components/atoms/badget/badget.doc.mdx +0 -46
- package/src/components/atoms/badget/badget.stories.tsx +0 -75
- package/src/components/atoms/button/button.doc.mdx +0 -59
- package/src/components/atoms/button/button.stories.tsx +0 -173
- package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
- package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
- package/src/components/atoms/chip/chip.doc.mdx +0 -47
- package/src/components/atoms/chip/chip.stories.tsx +0 -64
- package/src/components/atoms/divider/divider.doc.mdx +0 -42
- package/src/components/atoms/divider/divider.stories.tsx +0 -33
- package/src/components/atoms/flex/flex.doc.mdx +0 -59
- package/src/components/atoms/flex/flex.stories.tsx +0 -70
- package/src/components/atoms/grid/grid.doc.mdx +0 -54
- package/src/components/atoms/grid/grid.stories.tsx +0 -71
- package/src/components/atoms/image/image.doc.mdx +0 -44
- package/src/components/atoms/image/image.stories.tsx +0 -48
- package/src/components/atoms/input/input.doc.mdx +0 -70
- package/src/components/atoms/input/input.stories.tsx +0 -113
- package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
- package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
- package/src/components/atoms/loader/loader.doc.mdx +0 -43
- package/src/components/atoms/loader/loader.stories.tsx +0 -104
- package/src/components/atoms/popover/popover.doc.mdx +0 -53
- package/src/components/atoms/popover/popover.stories.tsx +0 -24
- package/src/components/atoms/progress/progress.doc.mdx +0 -48
- package/src/components/atoms/progress/progress.stories.tsx +0 -39
- package/src/components/atoms/radio/radio.doc.mdx +0 -62
- package/src/components/atoms/radio/radio.stories.tsx +0 -48
- package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
- package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
- package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
- package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
- package/src/components/atoms/slide/slide.doc.mdx +0 -46
- package/src/components/atoms/slide/slide.stories.tsx +0 -120
- package/src/components/atoms/slider/slider.doc.mdx +0 -49
- package/src/components/atoms/slider/slider.stories.tsx +0 -29
- package/src/components/atoms/stack/stack.doc.mdx +0 -126
- package/src/components/atoms/stack/stack.stories.tsx +0 -283
- package/src/components/atoms/text/text.doc.mdx +0 -41
- package/src/components/atoms/text/text.stories.tsx +0 -66
- package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
- package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
- package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
- package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
- package/src/components/isolation/isolation.stories.tsx +0 -202
- package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
- package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
- package/src/components/molecules/alert/alert.doc.mdx +0 -48
- package/src/components/molecules/alert/alert.stories.tsx +0 -40
- package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
- package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
- package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
- package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
- package/src/components/molecules/card/card.doc.mdx +0 -54
- package/src/components/molecules/card/card.stories.tsx +0 -57
- package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
- package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
- package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
- package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
- package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
- package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
- package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
- package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
- package/src/components/molecules/field/field.doc.mdx +0 -43
- package/src/components/molecules/field/field.stories.tsx +0 -42
- package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
- package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
- package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
- package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
- package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
- package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
- package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
- package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
- package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
- package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
- package/src/components/molecules/select/select.doc.mdx +0 -75
- package/src/components/molecules/select/select.stories.tsx +0 -85
- package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
- package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
- package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
- package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
- package/src/components/molecules/table/table.doc.mdx +0 -140
- package/src/components/molecules/table/table.stories.tsx +0 -402
- package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
- package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
- package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
- package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
- package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
- package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
- package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
- package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -132
- package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
- package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
- package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
- package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
- package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
- package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
- package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
- package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
- package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
- package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
- package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
- package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
- package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
- package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
- package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
- package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
- package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
- package/src/components/organisms/toast/toast.doc.mdx +0 -50
- package/src/components/organisms/toast/toast.stories.tsx +0 -137
- package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
- package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
- package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
- package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
- package/src/components/templates/layout/layout.doc.mdx +0 -53
- package/src/components/templates/layout/layout.stories.tsx +0 -113
- package/src/components/templates/page/page.doc.mdx +0 -86
- package/src/components/templates/page/page.stories.tsx +0 -97
- package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
- package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
|
@@ -1,315 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
2
|
+
import { FaArrowRight, FaCheck, FaGithub, FaLayerGroup, FaNpm, FaRocket } from "react-icons/fa";
|
|
3
|
+
import ITGrid from "../components/atoms/grid/grid";
|
|
2
4
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
FaSlidersH,
|
|
18
|
-
FaTable,
|
|
19
|
-
} from "react-icons/fa";
|
|
20
|
-
import ITBadget from "@/components/atoms/badget/badget";
|
|
21
|
-
import ITButton from "@/components/atoms/button/button";
|
|
22
|
-
import ITFlex from "@/components/atoms/flex/flex";
|
|
23
|
-
import ITGrid from "@/components/atoms/grid/grid";
|
|
24
|
-
import ITStack from "@/components/atoms/stack/stack";
|
|
25
|
-
import ITText from "@/components/atoms/text/text";
|
|
26
|
-
import {
|
|
27
|
-
SANDBOX_GROUPS,
|
|
28
|
-
TOTAL_ITEMS,
|
|
29
|
-
} from "./navigation";
|
|
5
|
+
BloqueCodigo,
|
|
6
|
+
BotonAccion,
|
|
7
|
+
BotonCopiar,
|
|
8
|
+
CHIP,
|
|
9
|
+
EnlaceMono,
|
|
10
|
+
EYEBROW,
|
|
11
|
+
Etiqueta,
|
|
12
|
+
FILETE,
|
|
13
|
+
SectionHeading,
|
|
14
|
+
} from "@/sandbox/ui";
|
|
15
|
+
import { SANDBOX_GROUPS, TOTAL_ITEMS } from "./navigation";
|
|
16
|
+
import { GROUP_ICONS } from "./icons";
|
|
17
|
+
import { translateLabel } from "./i18n";
|
|
18
|
+
import { useITTranslation } from "@/i18n";
|
|
30
19
|
|
|
31
|
-
/** Props for the sandbox landing page. */
|
|
32
20
|
export interface LandingShowcaseProps {
|
|
33
|
-
/**
|
|
21
|
+
/** Abre la página de un componente del sandbox. */
|
|
34
22
|
onOpenItem: (group: string, item: string) => void;
|
|
35
|
-
/**
|
|
23
|
+
/** Vuelve al portafolio (`/`). */
|
|
36
24
|
onOpenPortfolio: () => void;
|
|
37
25
|
}
|
|
38
26
|
|
|
39
|
-
/** Props for the local `SectionHeading` helper. */
|
|
40
|
-
interface SectionHeadingProps {
|
|
41
|
-
/** Small uppercase kicker rendered above the title. */
|
|
42
|
-
eyebrow: string;
|
|
43
|
-
/** Section title, always rendered as an `<h2>`. */
|
|
44
|
-
title: string;
|
|
45
|
-
/** Optional supporting sentence rendered below the title. */
|
|
46
|
-
subtitle?: string;
|
|
47
|
-
/** Extra classes for the heading wrapper (spacing, etc.). */
|
|
48
|
-
className?: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Icon per sandbox group id. */
|
|
52
|
-
const GROUP_ICONS: Record<string, ReactNode> = {
|
|
53
|
-
general: <FaHome />,
|
|
54
|
-
struc: <FaCreditCard />,
|
|
55
|
-
forms: <FaKeyboard />,
|
|
56
|
-
data: <FaTable />,
|
|
57
|
-
nav: <FaSlidersH />,
|
|
58
|
-
feed: <FaRegBell />,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Literal per-index gradient classes for the family and stat tiles. Tailwind
|
|
63
|
-
* v4 cannot see runtime-built class names, so every gradient is written out
|
|
64
|
-
* in full and indexed by position.
|
|
65
|
-
*/
|
|
66
|
-
const GROUP_ACCENTS = [
|
|
67
|
-
"from-primary-500 to-info-500",
|
|
68
|
-
"from-purple-500 to-primary-500",
|
|
69
|
-
"from-primary-600 to-purple-600",
|
|
70
|
-
"from-info-500 to-purple-500",
|
|
71
|
-
"from-purple-600 to-info-600",
|
|
72
|
-
"from-primary-500 to-purple-500",
|
|
73
|
-
];
|
|
74
|
-
|
|
75
27
|
const GITHUB_URL = "https://github.com/maag070208/AXZY_UI_SYSTEM";
|
|
28
|
+
const NPM_URL = "https://www.npmjs.com/package/@axzydev/axzy_ui_system";
|
|
76
29
|
const INSTALL_CMD = "pnpm add @axzydev/axzy_ui_system";
|
|
77
30
|
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* contexts, embedded webviews). Returns whether the copy succeeded.
|
|
82
|
-
*/
|
|
83
|
-
const copyText = async (text: string): Promise<boolean> => {
|
|
84
|
-
try {
|
|
85
|
-
if (navigator.clipboard?.writeText) {
|
|
86
|
-
await navigator.clipboard.writeText(text);
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
} catch {
|
|
90
|
-
/* fall through to the legacy path */
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let textarea: HTMLTextAreaElement | null = null;
|
|
94
|
-
try {
|
|
95
|
-
textarea = document.createElement("textarea");
|
|
96
|
-
textarea.value = text;
|
|
97
|
-
textarea.setAttribute("readonly", "");
|
|
98
|
-
textarea.style.position = "fixed";
|
|
99
|
-
textarea.style.opacity = "0";
|
|
100
|
-
document.body.appendChild(textarea);
|
|
101
|
-
textarea.select();
|
|
102
|
-
return document.execCommand("copy");
|
|
103
|
-
} catch {
|
|
104
|
-
return false;
|
|
105
|
-
} finally {
|
|
106
|
-
textarea?.remove();
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Clipboard button that flips to a "Copiado" confirmation for 2s.
|
|
112
|
-
*
|
|
113
|
-
* `ITButton` writes `box-shadow` as an inline style on focus, so the visible
|
|
114
|
-
* keyboard ring is owned by the wrapper element that uses `focus-within`
|
|
115
|
-
* (see `LandingShowcase`) instead of a `focus-visible:` class here.
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* <CopyButton text="pnpm add @axzydev/axzy_ui_system" />
|
|
119
|
-
*/
|
|
120
|
-
const CopyButton = ({ text }: { text: string }) => {
|
|
121
|
-
const [copied, setCopied] = useState(false);
|
|
122
|
-
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
123
|
-
|
|
124
|
-
useEffect(
|
|
125
|
-
() => () => {
|
|
126
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
127
|
-
},
|
|
128
|
-
[],
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
const handleCopy = async () => {
|
|
132
|
-
const ok = await copyText(text);
|
|
133
|
-
if (!ok) return;
|
|
134
|
-
setCopied(true);
|
|
135
|
-
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
136
|
-
timeoutRef.current = setTimeout(() => setCopied(false), 2000);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<span aria-live="polite" className="inline-flex">
|
|
141
|
-
<ITButton
|
|
142
|
-
variant="text"
|
|
143
|
-
color="gray"
|
|
144
|
-
size="sm"
|
|
145
|
-
onClick={handleCopy}
|
|
146
|
-
className="!font-semibold"
|
|
147
|
-
>
|
|
148
|
-
<ITFlex align="center" gap={1.5}>
|
|
149
|
-
{copied ? (
|
|
150
|
-
<FaCheck size={10} className="text-emerald-400" />
|
|
151
|
-
) : (
|
|
152
|
-
<FaCopy size={10} />
|
|
153
|
-
)}
|
|
154
|
-
{copied ? "Copiado" : "Copiar"}
|
|
155
|
-
</ITFlex>
|
|
156
|
-
</ITButton>
|
|
157
|
-
</span>
|
|
158
|
-
);
|
|
159
|
-
};
|
|
31
|
+
/** Shared stagger offset for the masthead entrance cascade (`it-reveal`). */
|
|
32
|
+
const reveal = (delay: number): CSSProperties =>
|
|
33
|
+
({ "--it-delay": `${delay}ms` }) as CSSProperties;
|
|
160
34
|
|
|
161
35
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* @example
|
|
165
|
-
* <CodeBlock code="pnpm add pkg" filename="terminal" />
|
|
36
|
+
* i18n keys for the "built in" feature list, rendered in order inside the
|
|
37
|
+
* quickstart section.
|
|
166
38
|
*/
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
</div>
|
|
175
|
-
)}
|
|
176
|
-
<div className="relative bg-slate-950">
|
|
177
|
-
<pre className="p-4 text-xs font-mono overflow-x-auto leading-relaxed text-slate-200">
|
|
178
|
-
<code>{code}</code>
|
|
179
|
-
</pre>
|
|
180
|
-
</div>
|
|
181
|
-
</div>
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Uniform section heading: uppercase eyebrow + `<h2>` title + subtitle.
|
|
186
|
-
* Used by every section so the document outline stays consistent.
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* <SectionHeading eyebrow="Catálogo" title="Explora por familia" className="!mb-6" />
|
|
190
|
-
*/
|
|
191
|
-
const SectionHeading = ({
|
|
192
|
-
eyebrow,
|
|
193
|
-
title,
|
|
194
|
-
subtitle,
|
|
195
|
-
className = "",
|
|
196
|
-
}: SectionHeadingProps) => (
|
|
197
|
-
<ITStack spacing={1} className={className}>
|
|
198
|
-
<ITText
|
|
199
|
-
as="p"
|
|
200
|
-
className="!text-[11px] !font-bold uppercase !tracking-wider text-primary-600 dark:text-primary-400"
|
|
201
|
-
>
|
|
202
|
-
{eyebrow}
|
|
203
|
-
</ITText>
|
|
204
|
-
<ITText
|
|
205
|
-
as="h2"
|
|
206
|
-
className="!text-xl !font-bold !tracking-tight text-slate-900 dark:text-white"
|
|
207
|
-
>
|
|
208
|
-
{title}
|
|
209
|
-
</ITText>
|
|
210
|
-
{subtitle && (
|
|
211
|
-
<ITText as="p" className="!text-sm text-slate-500 dark:text-slate-400">
|
|
212
|
-
{subtitle}
|
|
213
|
-
</ITText>
|
|
214
|
-
)}
|
|
215
|
-
</ITStack>
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Purely decorative library preview card shown in the hero on `xl` screens.
|
|
220
|
-
* Hidden from assistive tech — it duplicates no real content.
|
|
221
|
-
*
|
|
222
|
-
* @example
|
|
223
|
-
* <HeroLibraryPreview />
|
|
224
|
-
*/
|
|
225
|
-
const HeroLibraryPreview = () => (
|
|
226
|
-
<div
|
|
227
|
-
aria-hidden
|
|
228
|
-
className="hidden w-[340px] shrink-0 justify-end xl:flex"
|
|
229
|
-
>
|
|
230
|
-
<div
|
|
231
|
-
className="it-landing-float w-full overflow-hidden rounded-2xl border border-slate-200/80 bg-white/85 shadow-xl backdrop-blur-sm dark:border-slate-700/70 dark:bg-slate-900/85"
|
|
232
|
-
style={{ animationDelay: "0.8s" }}
|
|
233
|
-
>
|
|
234
|
-
{/* fake toolbar */}
|
|
235
|
-
<div className="flex items-center gap-1.5 border-b border-slate-200/80 px-4 py-3 dark:border-slate-700/70">
|
|
236
|
-
<span className="h-2.5 w-2.5 rounded-full bg-danger-400/70" />
|
|
237
|
-
<span className="h-2.5 w-2.5 rounded-full bg-warning-400/70" />
|
|
238
|
-
<span className="h-2.5 w-2.5 rounded-full bg-success-400/70" />
|
|
239
|
-
<span className="ml-2 h-2 w-24 rounded-full bg-slate-200 dark:bg-slate-700" />
|
|
240
|
-
</div>
|
|
241
|
-
|
|
242
|
-
{/* mini table skeleton */}
|
|
243
|
-
<div className="px-4 pt-4">
|
|
244
|
-
<div className="flex items-center justify-between">
|
|
245
|
-
<span className="h-2.5 w-20 rounded-full bg-slate-200 dark:bg-slate-700" />
|
|
246
|
-
<span className="h-4 w-14 rounded-full bg-primary-100 dark:bg-primary-900/50" />
|
|
247
|
-
</div>
|
|
248
|
-
|
|
249
|
-
<div className="mt-4 space-y-3">
|
|
250
|
-
<div className="flex items-center gap-3">
|
|
251
|
-
<span className="h-6 w-6 flex-shrink-0 rounded-md bg-gradient-to-br from-primary-500 to-info-500 opacity-80" />
|
|
252
|
-
<span className="h-2 w-[68%] rounded-full bg-slate-200 dark:bg-slate-700" />
|
|
253
|
-
</div>
|
|
254
|
-
<div className="flex items-center gap-3">
|
|
255
|
-
<span className="h-6 w-6 flex-shrink-0 rounded-md bg-gradient-to-br from-purple-500 to-primary-500 opacity-80" />
|
|
256
|
-
<span className="h-2 w-[92%] rounded-full bg-slate-200 dark:bg-slate-700" />
|
|
257
|
-
</div>
|
|
258
|
-
<div className="flex items-center gap-3">
|
|
259
|
-
<span className="h-6 w-6 flex-shrink-0 rounded-md bg-gradient-to-br from-info-500 to-purple-500 opacity-80" />
|
|
260
|
-
<span className="h-2 w-[54%] rounded-full bg-slate-200 dark:bg-slate-700" />
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
|
|
265
|
-
{/* fake action + status */}
|
|
266
|
-
<div className="mt-5 flex items-center justify-between border-t border-slate-200/80 px-4 py-3.5 dark:border-slate-700/70">
|
|
267
|
-
<span className="inline-flex items-center rounded-lg bg-primary-500 px-3 py-1.5 text-[10px] font-bold tracking-wide text-white shadow-sm">
|
|
268
|
-
ITButton
|
|
269
|
-
</span>
|
|
270
|
-
<span className="inline-flex items-center gap-1.5 rounded-full border border-success-500/40 px-2.5 py-1 text-[10px] font-semibold text-success-600 dark:text-success-400">
|
|
271
|
-
<span className="h-1.5 w-1.5 rounded-full bg-success-500" />
|
|
272
|
-
Tipado
|
|
273
|
-
</span>
|
|
274
|
-
</div>
|
|
275
|
-
</div>
|
|
276
|
-
</div>
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
const STATS = [
|
|
280
|
-
{
|
|
281
|
-
label: "Componentes",
|
|
282
|
-
value: `${TOTAL_ITEMS}`,
|
|
283
|
-
hint: "páginas documentadas",
|
|
284
|
-
icon: <FaLayerGroup />,
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
label: "Familias",
|
|
288
|
-
value: `${SANDBOX_GROUPS.length}`,
|
|
289
|
-
hint: "grupos de navegación",
|
|
290
|
-
icon: <FaFolderOpen />,
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
label: "TypeScript",
|
|
294
|
-
value: "100%",
|
|
295
|
-
hint: "tipado estricto",
|
|
296
|
-
icon: <FaCode />,
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
label: "UI deps",
|
|
300
|
-
value: "0",
|
|
301
|
-
hint: "sin runtime extra",
|
|
302
|
-
icon: <FaBoxOpen />,
|
|
303
|
-
},
|
|
304
|
-
];
|
|
305
|
-
|
|
306
|
-
const FEATURES = [
|
|
307
|
-
"Tailwind CSS v4 con tokens de tema en runtime",
|
|
308
|
-
"Accesibilidad: roles, foco y nombres accesibles",
|
|
309
|
-
"Dark mode automático vía ITThemeProvider",
|
|
310
|
-
"Tree-shakeable: solo importas lo que usas",
|
|
311
|
-
"Sin dependencias de UI de terceros",
|
|
312
|
-
"Documentado con ejemplos ejecutables",
|
|
39
|
+
const FEATURE_KEYS = [
|
|
40
|
+
"showcase.landing.featureTokens",
|
|
41
|
+
"showcase.landing.featureA11y",
|
|
42
|
+
"showcase.landing.featureDarkMode",
|
|
43
|
+
"showcase.landing.featureTreeShakeable",
|
|
44
|
+
"showcase.landing.featureNoDeps",
|
|
45
|
+
"showcase.landing.featureDocumented",
|
|
313
46
|
];
|
|
314
47
|
|
|
315
48
|
const QUICKSTART_CODE = `import { ITThemeProvider, ITButton } from "@axzydev/axzy_ui_system"
|
|
@@ -324,331 +57,242 @@ export default function App() {
|
|
|
324
57
|
}`;
|
|
325
58
|
|
|
326
59
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
60
|
+
* Landing del sandbox (`#ui-system`): hoja técnica con masthead, banda de
|
|
61
|
+
* métricas derivadas, índice del catálogo por familia, quickstart y cierre.
|
|
62
|
+
*
|
|
63
|
+
* Es la misma lengua visual que el portafolio (filetes de 1px, mono para
|
|
64
|
+
* metadatos, un solo acento) para que las dos superficies se lean como un
|
|
65
|
+
* sistema y no como dos proyectos distintos.
|
|
329
66
|
*
|
|
330
67
|
* @example
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* />
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <LandingShowcase onOpenItem={goToItem} onOpenPortfolio={goToPortfolio} />
|
|
70
|
+
* ```
|
|
335
71
|
*/
|
|
336
|
-
export function LandingShowcase({
|
|
337
|
-
|
|
338
|
-
onOpenPortfolio,
|
|
339
|
-
}: LandingShowcaseProps) {
|
|
340
|
-
return (
|
|
341
|
-
<ITStack spacing={10} className="animate-fadeIn pb-5">
|
|
342
|
-
{/* ─── HERO ─── */}
|
|
343
|
-
<section
|
|
344
|
-
aria-labelledby="ui-system-hero-title"
|
|
345
|
-
className="relative overflow-hidden rounded-3xl bg-gradient-to-br from-primary-50 via-white to-purple-50 dark:from-primary-950/30 dark:via-slate-900 dark:to-purple-950/30 px-8 py-14 sm:px-14"
|
|
346
|
-
>
|
|
347
|
-
<div
|
|
348
|
-
aria-hidden
|
|
349
|
-
className="it-landing-float pointer-events-none absolute -top-24 -right-16 h-72 w-72 rounded-full bg-primary-400/20 blur-3xl"
|
|
350
|
-
/>
|
|
351
|
-
<div
|
|
352
|
-
aria-hidden
|
|
353
|
-
className="it-landing-float pointer-events-none absolute -bottom-24 -left-16 h-72 w-72 rounded-full bg-purple-400/20 blur-3xl"
|
|
354
|
-
style={{ animationDelay: "1.5s" }}
|
|
355
|
-
/>
|
|
356
|
-
<div
|
|
357
|
-
aria-hidden
|
|
358
|
-
className="it-landing-grid pointer-events-none absolute inset-0 text-slate-400/50 dark:text-slate-600/40"
|
|
359
|
-
/>
|
|
72
|
+
export function LandingShowcase({ onOpenItem, onOpenPortfolio }: LandingShowcaseProps) {
|
|
73
|
+
const { t } = useITTranslation();
|
|
360
74
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
<ITBadget
|
|
368
|
-
label="v1.3.0 · Tailwind v4"
|
|
369
|
-
color="primary"
|
|
370
|
-
variant="outlined"
|
|
371
|
-
className="w-fit"
|
|
372
|
-
/>
|
|
373
|
-
</div>
|
|
75
|
+
const metricas = [
|
|
76
|
+
{ label: t("showcase.landing.statComponents"), value: `${TOTAL_ITEMS}` },
|
|
77
|
+
{ label: t("showcase.landing.statFamilies"), value: `${SANDBOX_GROUPS.length}` },
|
|
78
|
+
{ label: "TypeScript", value: "100%" },
|
|
79
|
+
{ label: t("showcase.landing.statUiDeps"), value: "0" },
|
|
80
|
+
];
|
|
374
81
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
<
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
Una librería React + TypeScript con Tailwind CSS v4: accesible,
|
|
393
|
-
temable y lista para producción. Explora {TOTAL_ITEMS} páginas en{" "}
|
|
394
|
-
{SANDBOX_GROUPS.length} familias.
|
|
395
|
-
</ITText>
|
|
82
|
+
return (
|
|
83
|
+
<div className="animate-fadeIn pb-4">
|
|
84
|
+
{/* ─── 01 · MASTHEAD ─── */}
|
|
85
|
+
<section aria-labelledby="ui-system-hero-title">
|
|
86
|
+
<div className={`flex flex-wrap items-center justify-between gap-4 border-b pb-4 ${FILETE}`}>
|
|
87
|
+
<span className={`it-reveal ${EYEBROW}`}>
|
|
88
|
+
{`v${__APP_VERSION__} · Tailwind v4 · MIT`}
|
|
89
|
+
</span>
|
|
90
|
+
<div className="flex items-center gap-5">
|
|
91
|
+
<EnlaceMono href={GITHUB_URL} icono={<FaGithub size={11} />}>
|
|
92
|
+
GitHub
|
|
93
|
+
</EnlaceMono>
|
|
94
|
+
<EnlaceMono href={NPM_URL} icono={<FaNpm size={12} />}>
|
|
95
|
+
npm
|
|
96
|
+
</EnlaceMono>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
396
99
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
100
|
+
<div className="pb-10 pt-10 sm:pt-12">
|
|
101
|
+
<h1
|
|
102
|
+
id="ui-system-hero-title"
|
|
103
|
+
className="it-reveal font-display text-[38px] font-bold leading-[1.06] tracking-[-0.015em] text-slate-900 dark:text-white sm:text-[52px]"
|
|
104
|
+
style={reveal(60)}
|
|
105
|
+
>
|
|
106
|
+
{t("showcase.landing.heroTitleLead")}{" "}
|
|
107
|
+
<span className="text-primary-600 dark:text-primary-400">
|
|
108
|
+
{t("showcase.landing.heroTitleHighlight")}
|
|
109
|
+
</span>
|
|
110
|
+
</h1>
|
|
111
|
+
|
|
112
|
+
<p
|
|
113
|
+
className="it-reveal mt-6 max-w-[64ch] text-[15.5px] leading-[1.75] text-slate-600 dark:text-slate-300 sm:text-[17px]"
|
|
114
|
+
style={reveal(130)}
|
|
115
|
+
>
|
|
116
|
+
{t("showcase.landing.heroSubtitle", {
|
|
117
|
+
pages: TOTAL_ITEMS,
|
|
118
|
+
families: SANDBOX_GROUPS.length,
|
|
119
|
+
})}
|
|
120
|
+
</p>
|
|
121
|
+
|
|
122
|
+
<div className="it-reveal mt-8 flex flex-wrap items-center gap-3" style={reveal(200)}>
|
|
123
|
+
<BotonAccion
|
|
124
|
+
variante="filled"
|
|
125
|
+
icono={<FaRocket size={12} />}
|
|
126
|
+
onClick={() => onOpenItem("general", "getting-started")}
|
|
403
127
|
>
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
>
|
|
411
|
-
Explorar componentes
|
|
412
|
-
</ITButton>
|
|
413
|
-
<ITButton
|
|
414
|
-
variant="outlined"
|
|
415
|
-
color="secondary"
|
|
416
|
-
size="lg"
|
|
417
|
-
icon={<FaLayerGroup size={13} />}
|
|
418
|
-
onClick={onOpenPortfolio}
|
|
419
|
-
>
|
|
420
|
-
Ver portafolio
|
|
421
|
-
</ITButton>
|
|
422
|
-
</ITFlex>
|
|
423
|
-
|
|
424
|
-
<div
|
|
425
|
-
className="it-landing-rise mt-7 inline-flex flex-wrap items-center gap-x-3 gap-y-2 rounded-2xl border border-primary-200 bg-gradient-to-r from-primary-50 to-purple-50 px-4 py-2 shadow-sm dark:border-primary-800/50 dark:from-primary-950/30 dark:to-purple-950/30"
|
|
426
|
-
style={{ animationDelay: "280ms" }}
|
|
128
|
+
{t("showcase.landing.exploreComponents")}
|
|
129
|
+
</BotonAccion>
|
|
130
|
+
<BotonAccion
|
|
131
|
+
variante="outlined"
|
|
132
|
+
icono={<FaLayerGroup size={12} />}
|
|
133
|
+
onClick={onOpenPortfolio}
|
|
427
134
|
>
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
{INSTALL_CMD}
|
|
431
|
-
</code>
|
|
432
|
-
<span className="inline-flex items-center rounded-lg border border-primary-200/90 bg-white/85 focus-within:ring-2 focus-within:ring-inset focus-within:ring-primary-500 dark:border-primary-800/90 dark:bg-slate-900/70">
|
|
433
|
-
<CopyButton text={INSTALL_CMD} />
|
|
434
|
-
</span>
|
|
435
|
-
</div>
|
|
135
|
+
{t("showcase.landing.viewPortfolio")}
|
|
136
|
+
</BotonAccion>
|
|
436
137
|
</div>
|
|
437
138
|
|
|
438
|
-
<
|
|
139
|
+
<div
|
|
140
|
+
className={`it-reveal mt-8 inline-flex flex-wrap items-center gap-x-3 gap-y-2 rounded-[10px] border px-4 py-2 ${FILETE}`}
|
|
141
|
+
style={reveal(260)}
|
|
142
|
+
>
|
|
143
|
+
<FaNpm size={15} className="shrink-0 text-primary-700 dark:text-primary-500" />
|
|
144
|
+
<code className="font-mono text-xs text-slate-700 dark:text-slate-200">
|
|
145
|
+
{INSTALL_CMD}
|
|
146
|
+
</code>
|
|
147
|
+
<span className={`border-l pl-3 ${FILETE}`}>
|
|
148
|
+
<BotonCopiar texto={INSTALL_CMD} />
|
|
149
|
+
</span>
|
|
150
|
+
</div>
|
|
439
151
|
</div>
|
|
440
152
|
</section>
|
|
441
153
|
|
|
442
|
-
{/* ───
|
|
443
|
-
<section aria-label="
|
|
444
|
-
<
|
|
445
|
-
{
|
|
446
|
-
<
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
GROUP_ACCENTS[index % GROUP_ACCENTS.length]
|
|
458
|
-
}`}
|
|
459
|
-
>
|
|
460
|
-
{stat.icon}
|
|
461
|
-
</span>
|
|
462
|
-
</div>
|
|
463
|
-
|
|
464
|
-
<div className="mt-auto">
|
|
465
|
-
<ITText
|
|
466
|
-
as="p"
|
|
467
|
-
className="!text-sm !font-semibold text-primary-600 dark:text-primary-400"
|
|
468
|
-
>
|
|
469
|
-
{stat.label}
|
|
470
|
-
</ITText>
|
|
471
|
-
<ITText
|
|
472
|
-
as="p"
|
|
473
|
-
className="!mt-0.5 !text-[11px] text-slate-400 dark:text-slate-500"
|
|
474
|
-
>
|
|
475
|
-
{stat.hint}
|
|
476
|
-
</ITText>
|
|
477
|
-
</div>
|
|
478
|
-
</div>
|
|
479
|
-
</ITGrid>
|
|
154
|
+
{/* ─── BANDA DE MÉTRICAS ─── */}
|
|
155
|
+
<section aria-label={t("showcase.landing.ariaStats")}>
|
|
156
|
+
<dl className={`grid grid-cols-2 border-b sm:grid-cols-4 ${FILETE}`}>
|
|
157
|
+
{metricas.map((metrica, indice) => (
|
|
158
|
+
<div
|
|
159
|
+
key={metrica.label}
|
|
160
|
+
className={`py-6 ${indice > 0 ? "sm:border-l sm:pl-6 " : ""}${
|
|
161
|
+
indice % 2 === 1 ? "border-l pl-6 " : ""
|
|
162
|
+
}${FILETE}`}
|
|
163
|
+
>
|
|
164
|
+
<dt className={EYEBROW}>{metrica.label}</dt>
|
|
165
|
+
<dd className="mt-2 font-display text-[30px] font-bold leading-none tracking-[-0.02em] tabular-nums text-slate-900 dark:text-white">
|
|
166
|
+
{metrica.value}
|
|
167
|
+
</dd>
|
|
168
|
+
</div>
|
|
480
169
|
))}
|
|
481
|
-
</
|
|
170
|
+
</dl>
|
|
482
171
|
</section>
|
|
483
172
|
|
|
484
|
-
{/* ───
|
|
485
|
-
<section>
|
|
173
|
+
{/* ─── 02 · CATÁLOGO ─── */}
|
|
174
|
+
<section className="pt-12 sm:pt-14">
|
|
486
175
|
<SectionHeading
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
176
|
+
index={1}
|
|
177
|
+
label={t("showcase.structure.navCatalog")}
|
|
178
|
+
title={t("showcase.landing.exploreTitle")}
|
|
179
|
+
subtitle={t("showcase.landing.exploreSubtitle")}
|
|
180
|
+
className="pb-7"
|
|
491
181
|
/>
|
|
492
182
|
|
|
493
|
-
<
|
|
183
|
+
<div className={`border-t ${FILETE}`}>
|
|
494
184
|
{SANDBOX_GROUPS.map((group, index) => (
|
|
495
|
-
<
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
185
|
+
<button
|
|
186
|
+
key={group.id}
|
|
187
|
+
type="button"
|
|
188
|
+
onClick={() => onOpenItem(group.id, group.subitems[0].id)}
|
|
189
|
+
className={`group grid w-full grid-cols-[auto_1fr_auto] items-center gap-x-5 gap-y-2 border-b py-4 text-left transition-colors hover:bg-slate-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500/60 dark:hover:bg-slate-900/60 ${FILETE}`}
|
|
190
|
+
>
|
|
191
|
+
<span className="font-mono text-[11px] tabular-nums text-slate-500 dark:text-slate-400">
|
|
192
|
+
{String(index + 1).padStart(2, "0")}
|
|
193
|
+
</span>
|
|
194
|
+
|
|
195
|
+
<span className="min-w-0">
|
|
196
|
+
<span className="flex items-center gap-2.5">
|
|
197
|
+
<span className="text-primary-700 dark:text-primary-500">
|
|
507
198
|
{GROUP_ICONS[group.id]}
|
|
508
199
|
</span>
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
className="min-w-0 flex-1 truncate !text-[15px] !font-bold !tracking-tight text-slate-900 dark:text-white"
|
|
512
|
-
>
|
|
513
|
-
{group.label}
|
|
514
|
-
</ITText>
|
|
515
|
-
<span className="inline-flex shrink-0 items-center rounded-full bg-slate-100 px-2 py-0.5 text-[11px] font-semibold tabular-nums text-slate-500 dark:bg-slate-800 dark:text-slate-400">
|
|
516
|
-
{group.subitems.length}
|
|
200
|
+
<span className="font-display text-[16px] font-bold tracking-[-0.02em] text-slate-900 dark:text-white">
|
|
201
|
+
{translateLabel(group.id, group.label, t)}
|
|
517
202
|
</span>
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
</span>
|
|
524
|
-
</div>
|
|
525
|
-
|
|
526
|
-
<div className="mt-auto flex flex-wrap gap-1.5">
|
|
527
|
-
{group.subitems.slice(0, 4).map((sub) => (
|
|
528
|
-
<span
|
|
529
|
-
key={sub.id}
|
|
530
|
-
className="rounded-md bg-slate-100 dark:bg-slate-800 px-2 py-0.5 text-[10px] font-medium text-slate-500 dark:text-slate-400"
|
|
531
|
-
>
|
|
532
|
-
{sub.label}
|
|
203
|
+
</span>
|
|
204
|
+
<span className="mt-2 flex flex-wrap gap-1.5">
|
|
205
|
+
{group.subitems.slice(0, 5).map((sub) => (
|
|
206
|
+
<span key={sub.id} className={CHIP}>
|
|
207
|
+
{translateLabel(sub.id, sub.label, t)}
|
|
533
208
|
</span>
|
|
534
209
|
))}
|
|
535
|
-
{group.subitems.length >
|
|
536
|
-
<span className=
|
|
537
|
-
|
|
210
|
+
{group.subitems.length > 5 && (
|
|
211
|
+
<span className={CHIP}>
|
|
212
|
+
{t("showcase.landing.moreItems", { count: group.subitems.length - 5 })}
|
|
538
213
|
</span>
|
|
539
214
|
)}
|
|
540
|
-
</
|
|
541
|
-
</
|
|
542
|
-
|
|
215
|
+
</span>
|
|
216
|
+
</span>
|
|
217
|
+
|
|
218
|
+
<span className="flex items-center gap-3 font-mono text-[11px] tabular-nums text-slate-500 dark:text-slate-400">
|
|
219
|
+
{group.subitems.length}
|
|
220
|
+
<FaArrowRight
|
|
221
|
+
size={10}
|
|
222
|
+
className="text-slate-300 transition-colors group-hover:text-primary-700 dark:text-slate-600 dark:group-hover:text-primary-500"
|
|
223
|
+
/>
|
|
224
|
+
</span>
|
|
225
|
+
</button>
|
|
543
226
|
))}
|
|
544
|
-
</
|
|
227
|
+
</div>
|
|
545
228
|
</section>
|
|
546
229
|
|
|
547
|
-
{/* ─── QUICKSTART ─── */}
|
|
548
|
-
<section>
|
|
230
|
+
{/* ─── 03 · QUICKSTART ─── */}
|
|
231
|
+
<section className="pt-12 sm:pt-14">
|
|
549
232
|
<SectionHeading
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
233
|
+
index={2}
|
|
234
|
+
label={t("showcase.landing.quickstartEyebrow")}
|
|
235
|
+
title={t("showcase.landing.quickstartTitle")}
|
|
236
|
+
subtitle={t("showcase.landing.quickstartSubtitle")}
|
|
237
|
+
className="pb-7"
|
|
554
238
|
/>
|
|
555
239
|
|
|
556
|
-
<ITGrid container spacing={
|
|
240
|
+
<ITGrid container spacing={8}>
|
|
557
241
|
<ITGrid item xs={12} lg={7}>
|
|
558
|
-
<
|
|
559
|
-
<ITFlex align="center" justify="between" gap={3}>
|
|
560
|
-
<ITText
|
|
561
|
-
as="p"
|
|
562
|
-
className="!text-[11px] !font-bold uppercase !tracking-wider text-slate-400 dark:text-slate-500"
|
|
563
|
-
>
|
|
564
|
-
Ejemplo mínimo
|
|
565
|
-
</ITText>
|
|
566
|
-
<span className="inline-flex items-center rounded-lg focus-within:ring-2 focus-within:ring-inset focus-within:ring-primary-500">
|
|
567
|
-
<CopyButton text={QUICKSTART_CODE} />
|
|
568
|
-
</span>
|
|
569
|
-
</ITFlex>
|
|
570
|
-
<CodeBlock filename="src/App.tsx" code={QUICKSTART_CODE} />
|
|
571
|
-
</ITStack>
|
|
242
|
+
<BloqueCodigo code={QUICKSTART_CODE} filename="App.tsx" />
|
|
572
243
|
</ITGrid>
|
|
573
244
|
|
|
574
245
|
<ITGrid item xs={12} lg={5}>
|
|
575
|
-
<
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
className=
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
{feature}
|
|
590
|
-
</span>
|
|
591
|
-
</li>
|
|
592
|
-
))}
|
|
593
|
-
</ul>
|
|
594
|
-
</div>
|
|
246
|
+
<p className={EYEBROW}>{t("showcase.landing.builtIn")}</p>
|
|
247
|
+
<ul className={`mt-4 border-t ${FILETE}`}>
|
|
248
|
+
{FEATURE_KEYS.map((key) => (
|
|
249
|
+
<li key={key} className={`flex gap-3 border-b py-3 ${FILETE}`}>
|
|
250
|
+
<FaCheck
|
|
251
|
+
size={10}
|
|
252
|
+
className="mt-1.5 shrink-0 text-primary-700 dark:text-primary-500"
|
|
253
|
+
/>
|
|
254
|
+
<span className="text-[13.5px] leading-relaxed text-slate-600 dark:text-slate-300">
|
|
255
|
+
{t(key)}
|
|
256
|
+
</span>
|
|
257
|
+
</li>
|
|
258
|
+
))}
|
|
259
|
+
</ul>
|
|
595
260
|
</ITGrid>
|
|
596
261
|
</ITGrid>
|
|
597
262
|
</section>
|
|
598
263
|
|
|
599
|
-
{/* ───
|
|
600
|
-
<section className=
|
|
601
|
-
<div
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
color="primary"
|
|
622
|
-
icon={<FaLayerGroup size={13} />}
|
|
623
|
-
onClick={onOpenPortfolio}
|
|
624
|
-
>
|
|
625
|
-
Portafolio
|
|
626
|
-
</ITButton>
|
|
627
|
-
<ITButton
|
|
628
|
-
variant="outlined"
|
|
629
|
-
color="secondary"
|
|
630
|
-
icon={<FaGithub size={13} />}
|
|
631
|
-
onClick={() =>
|
|
632
|
-
window.open(GITHUB_URL, "_blank", "noopener,noreferrer")
|
|
633
|
-
}
|
|
634
|
-
>
|
|
635
|
-
GitHub
|
|
636
|
-
</ITButton>
|
|
637
|
-
</ITFlex>
|
|
264
|
+
{/* ─── 04 · CIERRE ─── */}
|
|
265
|
+
<section className={`mt-12 border-t pt-12 sm:mt-14 ${FILETE}`}>
|
|
266
|
+
<div className="flex flex-col gap-8 lg:flex-row lg:items-end lg:justify-between">
|
|
267
|
+
<div className="min-w-0">
|
|
268
|
+
<p className={EYEBROW}>
|
|
269
|
+
<span className="tabular-nums">03</span>
|
|
270
|
+
{` — ${t("showcase.landing.ctaTitle")}`}
|
|
271
|
+
</p>
|
|
272
|
+
<h2 className="mt-3 font-display text-[30px] font-bold leading-[1.08] tracking-[-0.02em] text-slate-900 dark:text-white sm:text-[40px]">
|
|
273
|
+
{t("showcase.landing.ctaSubtitle")}
|
|
274
|
+
</h2>
|
|
275
|
+
<p className="mt-4 max-w-[62ch] text-[15px] leading-relaxed text-slate-600 dark:text-slate-300">
|
|
276
|
+
{t("showcase.landing.footerRun")}{" "}
|
|
277
|
+
<code className="rounded-[6px] border border-slate-200 bg-slate-50 px-1.5 py-0.5 font-mono text-[12px] text-slate-700 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-200">
|
|
278
|
+
pnpm dev
|
|
279
|
+
</code>{" "}
|
|
280
|
+
{t("showcase.landing.footerOpen")}{" "}
|
|
281
|
+
<code className="rounded-[6px] border border-slate-200 bg-slate-50 px-1.5 py-0.5 font-mono text-[12px] text-slate-700 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-200">
|
|
282
|
+
#ui-system
|
|
283
|
+
</code>{" "}
|
|
284
|
+
{t("showcase.landing.footerSuffix")}
|
|
285
|
+
</p>
|
|
638
286
|
</div>
|
|
639
287
|
|
|
640
|
-
<
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
pnpm storybook
|
|
647
|
-
</code>{" "}
|
|
648
|
-
para ver cada componente aislado.
|
|
649
|
-
</ITText>
|
|
288
|
+
<div className="flex shrink-0 flex-wrap items-center gap-3">
|
|
289
|
+
<Etiqueta>{`v${__APP_VERSION__}`}</Etiqueta>
|
|
290
|
+
<BotonAccion variante="neutral" onClick={onOpenPortfolio}>
|
|
291
|
+
{t("showcase.landing.viewPortfolio")}
|
|
292
|
+
</BotonAccion>
|
|
293
|
+
</div>
|
|
650
294
|
</div>
|
|
651
295
|
</section>
|
|
652
|
-
</
|
|
296
|
+
</div>
|
|
653
297
|
);
|
|
654
298
|
}
|