|
| 1 | +## Form Components |
| 2 | + |
| 3 | +- `FormInput.vue` |
| 4 | + - Purpose: Text/password/date/etc. input with floating label, validation, optional password toggle. |
| 5 | + - Props: `modelValue`, `label` (required), `type` (`text|password|date|time|datetime-local`), `placeholder`, `required`, `disabled`, `error`, `help`, `id`. |
| 6 | + - Emits: `update:modelValue`. |
| 7 | + - Usage: |
| 8 | + ```vue |
| 9 | + <FormInput v-model="form.email" label="Email" type="email" :error="errors.email" /> |
| 10 | + ``` |
| 11 | +
|
| 12 | +- `FormTextarea.vue` |
| 13 | + - Purpose: Textarea with floating label and validation. |
| 14 | + - Props: `modelValue`, `label` (required), `placeholder`, `rows`, `required`, `disabled`, `error`, `help`, `id`. |
| 15 | + - Emits: `update:modelValue`. |
| 16 | + - Usage: |
| 17 | + ```vue |
| 18 | + <FormTextarea v-model="form.bio" label="Bio" rows="4" :error="errors.bio" /> |
| 19 | + ``` |
| 20 | +
|
| 21 | +- `FormSelect.vue` |
| 22 | + - Purpose: Custom searchable single-select (combobox-like) with keyboard support and clear button. |
| 23 | + - Props: `modelValue`, `label` (required), `options` (array of objects), `optionLabel` (default `label`), `optionValue` (default `value`), `placeholder`, `loading`, `required`, `disabled`, `error`, `id`. |
| 24 | + - Emits: `update:modelValue`. |
| 25 | + - Usage: |
| 26 | + ```vue |
| 27 | + <FormSelect |
| 28 | + v-model="form.country" |
| 29 | + label="Country" |
| 30 | + :options="countries" |
| 31 | + optionLabel="name" |
| 32 | + optionValue="code" |
| 33 | + :loading="isLoading" |
| 34 | + :error="errors.country" |
| 35 | + /> |
| 36 | + ``` |
| 37 | +
|
| 38 | +- `FormCheckbox.vue` |
| 39 | + - Purpose: Single checkbox with label, help, and error. |
| 40 | + - Props: `modelValue` (Boolean), `label` (required), `required`, `disabled`, `error`, `help`, `id`. |
| 41 | + - Emits: `update:modelValue`. |
| 42 | + - Usage: |
| 43 | + ```vue |
| 44 | + <FormCheckbox v-model="form.terms" label="I agree to terms" :error="errors.terms" /> |
| 45 | + ``` |
| 46 | +
|
| 47 | +- `FormCheckboxGroup.vue` |
| 48 | + - Purpose: Grid of checkbox cards for multi-select. |
| 49 | + - Props: `modelValue` (Array), `options` (required), `optionLabel` (`name`), `optionValue` (`id`), `optionDescription` (`description`), `label`, `help`, `columns` (`auto` or number), `disabled`, `error`, `name`. |
| 50 | + - Emits: `update:modelValue`. |
| 51 | + - Usage: |
| 52 | + ```vue |
| 53 | + <FormCheckboxGroup |
| 54 | + v-model="form.tags" |
| 55 | + label="Tags" |
| 56 | + :options="tags" |
| 57 | + optionLabel="name" |
| 58 | + optionValue="id" |
| 59 | + optionDescription="description" |
| 60 | + columns="3" |
| 61 | + :error="errors.tags" |
| 62 | + /> |
| 63 | + ``` |
| 64 | +
|
| 65 | +- `FormRadioGroup.vue` |
| 66 | + - Purpose: Radio group with label/description per option. |
| 67 | + - Props: `modelValue` (String|Number|Boolean), `options` (required: `{ label, value, description? }`), `label`, `name`, `required`, `error`. |
| 68 | + - Emits: `update:modelValue`. |
| 69 | + - Usage: |
| 70 | + ```vue |
| 71 | + <FormRadioGroup |
| 72 | + v-model="form.plan" |
| 73 | + label="Plan" |
| 74 | + :options="[ |
| 75 | + { label: 'Free', value: 'free' }, |
| 76 | + { label: 'Pro', value: 'pro', description: 'Best for teams' } |
| 77 | + ]" |
| 78 | + :error="errors.plan" |
| 79 | + /> |
| 80 | + ``` |
| 81 | +
|
| 82 | +## Widgets Structure (recommended) |
| 83 | +
|
| 84 | +- Place reusable UI widgets under `resources/js/Components/Widgets/`. |
| 85 | +- Document each widget similarly: purpose, props, emits, usage snippet. |
| 86 | +
|
| 87 | +## General Components |
| 88 | +
|
| 89 | +- `Modal.vue` (`resources/js/Components/Modal.vue`) |
| 90 | + - Purpose: Accessible modal with focus trap, ESC/overlay close, size variants. |
| 91 | + - Props: `show` (Boolean), `size` (`sm|md|lg|xl|2xl|3xl|4xl|5xl|full`, default `md`), `closeOnClickOutside` (Boolean, default `true`). |
| 92 | + - Emits: `close`. |
| 93 | + - Slots: `title`, default, `footer`. |
| 94 | + - Usage: |
| 95 | + ```vue |
| 96 | + <Modal :show="open" size="md" @close="open = false"> |
| 97 | + <template #title>Confirm</template> |
| 98 | + <p>Are you sure?</p> |
| 99 | + <template #footer> |
| 100 | + <button @click="open = false">Cancel</button> |
| 101 | + </template> |
| 102 | + </Modal> |
| 103 | + ``` |
| 104 | +
|
| 105 | +- `Tabs.vue` (`resources/js/Components/Tabs.vue`) |
| 106 | + - Purpose: Responsive tabs (desktop tabs + mobile select). |
| 107 | + - Props: `v-model` (Number index), `tabs` (Array of strings or objects `{ name, icon?, color? }`). |
| 108 | + - Emits: `update:modelValue`. |
| 109 | + - Usage: |
| 110 | + ```vue |
| 111 | + <Tabs v-model="active" :tabs="[{ name: 'Profile' }, { name: 'Security', icon: 'document-text' }]"> |
| 112 | + <div v-if="active === 0">Profile content</div> |
| 113 | + <div v-else>Security content</div> |
| 114 | + </Tabs> |
| 115 | + ``` |
| 116 | +
|
| 117 | +- `PageHeader.vue` (`resources/js/Components/PageHeader.vue`) |
| 118 | + - Purpose: Page title/description with breadcrumbs and actions slot. |
| 119 | + - Props: `title` (required), `description`, `breadcrumbs` (Array `{ label, href? }`). |
| 120 | + - Slots: `actions`. |
| 121 | + - Usage: |
| 122 | + ```vue |
| 123 | + <PageHeader |
| 124 | + title="Users" |
| 125 | + description="Manage all users" |
| 126 | + :breadcrumbs="[{ label: 'Dashboard', href: route('dashboard') }, { label: 'Users' }]"> |
| 127 | + <template #actions> |
| 128 | + <button class="btn-primary btn-sm">Add User</button> |
| 129 | + </template> |
| 130 | + </PageHeader> |
| 131 | + ``` |
| 132 | +
|
| 133 | +- `FeatureCard.vue` (`resources/js/Components/FeatureCard.vue`) |
| 134 | + - Purpose: Highlight feature with icon, title, description, optional link. |
| 135 | + - Props: `title`, `description`, `icon` (path d), `link`, `color` (`teal|indigo|emerald`). |
| 136 | + - Slots: `icon` (optional). |
| 137 | + - Usage: |
| 138 | + ```vue |
| 139 | + <FeatureCard |
| 140 | + title="API Ready" |
| 141 | + description="Robust endpoints with auth" |
| 142 | + icon="M5 12h14" |
| 143 | + color="teal" |
| 144 | + /> |
| 145 | + ``` |
| 146 | +
|
| 147 | +- `CodeBlock.vue` (`resources/js/Components/CodeBlock.vue`) |
| 148 | + - Purpose: Syntax-highlighted code with optional copy button. |
| 149 | + - Props: `code` (String|Object), `language` (`javascript|php|html|css|bash|typescript|python|json|vue|jsx|tsx|auto`), `showCopyButton` (Boolean, default `true`). |
| 150 | + - Usage: |
| 151 | + ```vue |
| 152 | + <CodeBlock :code="snippet" language="vue" /> |
| 153 | + ``` |
| 154 | +
|
| 155 | +- `ArticleNavigation.vue` (`resources/js/Components/ArticleNavigation.vue`) |
| 156 | + - Purpose: Sticky article outline with scroll spy. |
| 157 | + - Props: `links` (Array `{ id, title }`). |
| 158 | + - Usage: |
| 159 | + ```vue |
| 160 | + <ArticleNavigation :links="[{ id:'intro', title:'Introduction' }, { id:'setup', title:'Setup' }]" /> |
| 161 | + ``` |
| 162 | +
|
| 163 | +- `ColorThemeSwitcher.vue` (`resources/js/Components/ColorThemeSwitcher.vue`) |
| 164 | + - Purpose: Theme color picker dropdown (stores choice in localStorage, applies via `applyThemeColor`). |
| 165 | + - Props: none (uses theme config from `utils/themeInit`). |
| 166 | + - Usage: |
| 167 | + ```vue |
| 168 | + <ColorThemeSwitcher /> |
| 169 | + ``` |
| 170 | +
|
| 171 | +- `Datatable.vue` (`resources/js/Components/Datatable.vue`) |
| 172 | + - Purpose: Feature-rich table (sorting, search, pagination client/server, bulk delete modal, export, row expansion). |
| 173 | + - Props (key): `data` (Array), `columns` (tanstack column defs), `title`, `enableSearch`, `enableExport`, `searchFields`, `emptyMessage`, `emptyDescription`, `exportFileName`, `pageSizeOptions`, `defaultPageSize`, `loading`, `error`, `bulkDeleteRoute`, `pagination` (object for server mode), `filters`, `formatExportData`, `routeName`, `routeParams`. |
| 174 | + - Emits: `update:pagination`, `bulk-delete`, `navigate`. |
| 175 | + - Slots: `row` via column renderers; built-in bulk delete modal. |
| 176 | + - Usage (client pagination): |
| 177 | + ```vue |
| 178 | + <Datatable |
| 179 | + :data="rows" |
| 180 | + :columns="columns" |
| 181 | + :search-fields="['name','email']" |
| 182 | + empty-message="No records" |
| 183 | + empty-description="Data will appear here" |
| 184 | + /> |
| 185 | + ``` |
| 186 | + - Usage (server pagination): |
| 187 | + ```vue |
| 188 | + <Datatable |
| 189 | + :data="rows" |
| 190 | + :columns="columns" |
| 191 | + :pagination="pagination" |
| 192 | + :loading="loading" |
| 193 | + :search-fields="['name']" |
| 194 | + @update:pagination="pagination = $event" |
| 195 | + /> |
| 196 | + ``` |
| 197 | +
|
| 198 | +- `NavProfile.vue` (`resources/js/Components/Nav/NavProfile.vue`) |
| 199 | + - Purpose: User profile dropdown (avatar) with role chip, quick links, and sign-out. |
| 200 | + - Behavior: Toggles on click; closes on outside click/ESC; highlights active route; permission-gated menu items. |
| 201 | + - Props: none (reads user/permissions from Inertia `page.props.auth.user`). |
| 202 | + - Usage: |
| 203 | + ```vue |
| 204 | + <NavProfile /> |
| 205 | + ``` |
| 206 | +
|
| 207 | +- `NavSidebarDesktop.vue` (`resources/js/Components/Nav/NavSidebarDesktop.vue`) |
| 208 | + - Purpose: Desktop sidebar navigation with sections, permission gating, parent/child routes, and expand/collapse behavior. |
| 209 | + - Behavior: Highlights current route; parent expands when its child is active; clicking parent while on its route toggles collapse; respects permissions for parents/children. |
| 210 | + - Props: none (uses Inertia page props for auth/permissions). |
| 211 | + - Usage: |
| 212 | + ```vue |
| 213 | + <!-- Uses internal navigationSections; example of shape if you customize --> |
| 214 | + <NavSidebarDesktop /> |
| 215 | + <!-- navigationSections item example (in component or via future injection): |
| 216 | + [ |
| 217 | + { |
| 218 | + items: [ |
| 219 | + { name: 'Dashboard', route: 'dashboard', icon: '<path ... />' }, |
| 220 | + { type: 'divider' }, |
| 221 | + ], |
| 222 | + }, |
| 223 | + { |
| 224 | + items: [ |
| 225 | + { |
| 226 | + name: 'System Settings', |
| 227 | + route: 'admin.setting.index', |
| 228 | + icon: '<path ... />', |
| 229 | + permission: 'manage-settings', |
| 230 | + children: [ |
| 231 | + { name: 'User Management', route: 'admin.user.index', permission: 'manage-users' }, |
| 232 | + { name: 'Access Control', route: 'admin.permission.role.index' }, |
| 233 | + ], |
| 234 | + }, |
| 235 | + { type: 'divider' }, |
| 236 | + ], |
| 237 | + }, |
| 238 | + ] |
| 239 | + --> |
| 240 | + ``` |
| 241 | +
|
| 242 | +## Widgets |
| 243 | +
|
| 244 | +- `ChartWidget.vue` |
| 245 | + - Purpose: Sparkline-style mini chart with percentage change. |
| 246 | + - Props: `title`, `value`, `change` (Number), `data` (Number[]), `color` (`blue|green|red|yellow|purple|emerald`). |
| 247 | + - Usage: |
| 248 | + ```vue |
| 249 | + <ChartWidget title="Revenue" value="$45,231" :change="12.5" :data="[30,40,35,50,70]" color="emerald" /> |
| 250 | + ``` |
| 251 | +
|
| 252 | +- `MetricWidget.vue` |
| 253 | + - Purpose: Bold metric card with brutalist styling and trend indicator. |
| 254 | + - Props: `title`, `value`, `trend` (`up|down|null`), `change` (Number), `svg`, `viewBox`, `color` (`blue|green|red|yellow|purple|primary`). |
| 255 | + - Usage: |
| 256 | + ```vue |
| 257 | + <MetricWidget title="Total Revenue" :value="84621" trend="up" :change="12.5" :svg="revenueIcon" color="emerald" /> |
| 258 | + ``` |
| 259 | +
|
| 260 | +- `ProgressWidget.vue` |
| 261 | + - Purpose: Progress bar card with percentage and description. |
| 262 | + - Props: `title`, `value` (Number), `max` (Number, default 100), `description`, `color` (`blue|green|red|yellow|purple|indigo`), `showPercentage` (Boolean). |
| 263 | + - Usage: |
| 264 | + ```vue |
| 265 | + <ProgressWidget title="Storage Used" :value="75" :max="100" description="75GB of 100GB used" color="blue" /> |
| 266 | + ``` |
| 267 | +
|
| 268 | +- `StatWidget.vue` |
| 269 | + - Purpose: Stat card with icon and optional trend label. |
| 270 | + - Props: `title`, `value`, `description`, `icon` (svg string), `trend` (`up|down|neutral`), `color` (`blue|green|red|yellow|purple`). |
| 271 | + - Usage: |
| 272 | + ```vue |
| 273 | + <StatWidget title="Total Users" value="1,234" description="Active this month" :icon="userIcon" trend="up" color="blue" /> |
| 274 | + ``` |
| 275 | +
|
| 276 | +- `StockWidget.vue` |
| 277 | + - Purpose: Stock price card with logo, price, and change indicator. |
| 278 | + - Props: `stock` ({ symbol, name, price, change, currency }), `size` (`sm|md|lg`), `src` (logo), `alt`. |
| 279 | + - Usage: |
| 280 | + ```vue |
| 281 | + <StockWidget :stock="{ symbol:'AAPL', name:'Apple Inc', price:'173.25', change:0.86, currency:'$' }" src="/apple.svg" alt="Apple" size="lg" /> |
| 282 | + ``` |
| 283 | +
|
| 284 | +## Charts |
| 285 | +
|
| 286 | +- `Charts/ApexAreaChart.vue` |
| 287 | + - Purpose: ApexCharts area chart with gradient fill and dark-mode support. |
| 288 | + - Props: `chartData` ({ labels: string[], datasets: [{ label, data[] }]}), `height` (default `400px`), `title`. |
| 289 | + - Usage: |
| 290 | + ```vue |
| 291 | + <ApexAreaChart :chartData="areaData" title="Revenue" height="320px" /> |
| 292 | + ``` |
| 293 | +
|
| 294 | +- `Charts/ApexLineChart.vue` |
| 295 | + - Purpose: ApexCharts line chart with smooth stroke and dark-mode support. |
| 296 | + - Props: same shape as area chart (`chartData`, `height`, `title`). |
| 297 | + - Usage: |
| 298 | + ```vue |
| 299 | + <ApexLineChart :chartData="lineData" title="Signups" height="320px" /> |
| 300 | + ``` |
| 301 | +
|
| 302 | +- `Charts/ApexBarChart.vue` |
| 303 | + - Purpose: ApexCharts bar chart for categorical comparisons. |
| 304 | + - Props: `chartData` ({ labels, datasets: [{ label, data[] }]}), `height`, `title`. |
| 305 | + - Usage: |
| 306 | + ```vue |
| 307 | + <ApexBarChart :chartData="barData" title="Sales by Region" height="320px" /> |
| 308 | + ``` |
| 309 | +
|
| 310 | +- `Charts/ApexDonutChart.vue` |
| 311 | + - Purpose: ApexCharts donut chart with totals and dark-mode support. |
| 312 | + - Props: `chartData` ({ labels, datasets: [{ data[] }]}), `height`, `title`. |
| 313 | + - Usage: |
| 314 | + ```vue |
| 315 | + <ApexDonutChart :chartData="donutData" title="Revenue Split" height="320px" /> |
| 316 | + ``` |
| 317 | +
|
0 commit comments