Merge remote-tracking branch 'origin/main' into cal/hosting-server-instances

# Conflicts:
#	apps/app-frontend/src/pages/Browse.vue
#	apps/app-frontend/src/pages/hosting/manage/Index.vue
#	apps/app-frontend/src/pages/instance/Index.vue
#	apps/app-frontend/src/pages/project/Index.vue
#	apps/app-frontend/src/routes.js
#	apps/frontend/src/locales/en-US/index.json
#	apps/frontend/src/middleware/project.global.ts
#	apps/frontend/src/pages/[type]/[project].vue
#	apps/frontend/src/pages/discover/[type]/index.vue
#	apps/frontend/src/pages/organization/[organization].vue
#	apps/frontend/src/pages/user/[user].vue
#	packages/ui/src/components/base/FloatingActionBar.vue
#	packages/ui/src/components/base/PageHeader.vue
#	packages/ui/src/components/base/StackedAdmonitions.vue
#	packages/ui/src/components/base/TeleportOverflowMenu.vue
#	packages/ui/src/components/base/index.ts
#	packages/ui/src/components/project/ProjectHeader.vue
#	packages/ui/src/components/servers/server-header/ServerManageHeader.vue
#	packages/ui/src/components/servers/server-header/index.ts
#	packages/ui/src/composables/index.ts
#	packages/ui/src/layouts/shared/browse-tab/composables/use-browse-search.ts
#	packages/ui/src/layouts/shared/browse-tab/header.vue
#	packages/ui/src/layouts/shared/browse-tab/layout.vue
#	packages/ui/src/layouts/shared/content-tab/components/ContentModpackCard.vue
#	packages/ui/src/layouts/shared/content-tab/layout.vue
#	packages/ui/src/layouts/shared/installation-settings/components/ContentDiffModal.vue
#	packages/ui/src/layouts/shared/installation-settings/providers/installation-settings.ts
#	packages/ui/src/layouts/wrapped/hosting/manage/[id]/index.vue
#	packages/ui/src/locales/cs-CZ/index.json
#	packages/ui/src/locales/de-CH/index.json
#	packages/ui/src/locales/de-DE/index.json
#	packages/ui/src/locales/es-419/index.json
#	packages/ui/src/locales/es-ES/index.json
#	packages/ui/src/locales/fr-FR/index.json
#	packages/ui/src/locales/hu-HU/index.json
#	packages/ui/src/locales/id-ID/index.json
#	packages/ui/src/locales/it-IT/index.json
#	packages/ui/src/locales/ja-JP/index.json
#	packages/ui/src/locales/ko-KR/index.json
#	packages/ui/src/locales/ms-MY/index.json
#	packages/ui/src/locales/nl-NL/index.json
#	packages/ui/src/locales/pl-PL/index.json
#	packages/ui/src/locales/pt-BR/index.json
#	packages/ui/src/locales/ru-RU/index.json
#	packages/ui/src/locales/sv-SE/index.json
#	packages/ui/src/locales/tr-TR/index.json
#	packages/ui/src/locales/uk-UA/index.json
#	packages/ui/src/locales/vi-VN/index.json
#	packages/ui/src/locales/zh-CN/index.json
#	packages/ui/src/locales/zh-TW/index.json
#	packages/ui/src/stories/base/PageHeader.stories.ts
#	packages/ui/src/utils/file-extensions.ts
This commit is contained in:
Calum H. (IMB11)
2026-08-03 18:39:37 +01:00
1294 changed files with 151547 additions and 35420 deletions
+128
View File
@@ -0,0 +1,128 @@
# Component Structure
## Component folders
Prefer giving non-trivial components their own folder:
```
components/
└── analytics-chart/
├── index.vue
├── analytics-chart-header.vue
├── analytics-chart-plot.vue
├── analytics-chart-data.ts
└── use-analytics-chart.ts
```
The folder name should match the public component name in kebab case. The main component in that folder should be `index.vue`.
This keeps imports short:
```ts
import AnalyticsChart from '@/components/analytics-chart/index.vue'
```
If the local resolver supports directory indexes, importing the folder is also fine:
```ts
import AnalyticsChart from '@/components/analytics-chart/'
```
Use the explicit `index.vue` import when the TypeScript setup cannot resolve the directory import reliably.
## Local implementation files
Keep files that only exist to support one component inside that component's folder:
```
analytics-chart/
├── index.vue
├── analytics-chart-header.vue
├── analytics-chart-plot.vue
├── analytics-chart-tooltip.vue
├── chart-ranges.ts
└── use-chart-hover-state.ts
```
Good candidates for local files:
- Small subcomponents used only by the main component
- Local composables used only by the main component or its local subcomponents
- Helpers that split up a large `<script setup>` block
- Types that describe local component state or props
This is preferred over allowing a single component file to grow into a large, hard-to-review script block.
## Naming local subcomponents
Local subcomponents should still have clear names that explain their relationship to the main component:
```
analytics-chart/
├── index.vue
├── analytics-chart-header.vue
└── analytics-chart-plot.vue
```
Avoid vague names that make a local component look like a standalone public component:
```
analytics-chart/
├── index.vue
├── events.vue
└── header.vue
```
If a file is local to `analytics-chart`, prefixing it with `analytics-chart-` makes that relationship clear when it appears in search results, editor tabs, and imports.
## Nesting
One level of nesting is usually enough.
Prefer this:
```
analytics-chart/
├── index.vue
├── analytics-chart-header.vue
├── analytics-chart-plot.vue
├── use-chart-hover-state.ts
└── use-chart-selection.ts
```
Avoid this unless a local area has become large enough to justify its own module boundary:
```
analytics-chart/
├── index.vue
├── header/
│ └── index.vue
└── plot/
├── index.vue
└── use-plot-state.ts
```
Subfolders are fine when they reduce real complexity, but do not create a folder for every small subcomponent by default. Deep nesting makes the file tree harder to scan and often adds duplicated names without improving ownership.
## When not to use a folder
Small, leaf components can stay as a single `.vue` file:
```
components/
├── avatar-stack.vue
├── empty-state.vue
└── project-status-pill.vue
```
Move a component into a folder once it grows local helpers, local composables, or local subcomponents.
## Public versus local components
Only the main `index.vue` should be treated as the public entry point for the folder. Other files in the folder are implementation details unless there is a clear reason to import them from outside.
If a local subcomponent starts being imported elsewhere, either:
- Promote it into its own component folder
- Move it to the nearest shared component area if it is genuinely reusable
- Keep it local and pass behavior through the main component if external imports would leak implementation details