New project cards (#5298)

* New project card

* no shadow on icons

* Remove updated label

* reduce tag count to 5

* improve envs

* fix: project card bottom row not growing

* move actions in grid mode

* focus changes + new project list component

* Allow more tags in grid mode, deprioritize non-loader tags

* fix prod deploy robots.txt

* remove unused id

* App cards

* prepr

* publish date + fix router links

* fix author hover underline in firefox

* perf: preload on search item hover

* remove unused filter

* remove option for old grid view

---------

Co-authored-by: tdgao <mr.trumgao@gmail.com>
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
Prospector
2026-02-07 11:18:59 -08:00
committed by GitHub
parent b6c22d6ca6
commit b005c1f522
46 changed files with 1343 additions and 1759 deletions

View File

@@ -369,6 +369,30 @@ export const commonMessages = defineMessages({
id: 'label.no-items',
defaultMessage: 'No items',
},
projectCreated: {
id: 'project.about.details.created',
defaultMessage: 'Created {date}',
},
projectSubmitted: {
id: 'project.about.details.submitted',
defaultMessage: 'Submitted {date}',
},
projectPublished: {
id: 'project.about.details.published',
defaultMessage: 'Published {date}',
},
projectUpdated: {
id: 'project.about.details.updated',
defaultMessage: 'Updated {date}',
},
projectDownloads: {
id: 'project.download-count-tooltip',
defaultMessage: '{count} {count, plural, one {download} other {downloads}}',
},
projectFollowers: {
id: 'project.follower-count-tooltip',
defaultMessage: '{count} {count, plural, one {followers} other {followers}}',
},
})
export const formFieldLabels = defineMessages({

View File

@@ -5,7 +5,13 @@ import { type Component, computed, readonly, type Ref, ref } from 'vue'
import { type LocationQueryRaw, type LocationQueryValue, useRoute } from 'vue-router'
import { defineMessage, useVIntl } from '../composables/i18n'
import { formatCategory, formatCategoryHeader, formatLoader } from './tag-messages.ts'
import {
DEFAULT_MOD_LOADERS,
DEFAULT_SHADER_LOADERS,
formatCategory,
formatCategoryHeader,
formatLoader,
} from './tag-messages.ts'
type BaseOption = {
id: string
@@ -245,7 +251,7 @@ export function useSearch(
display: 'expandable',
query_param: 'g',
supports_negative_filter: true,
default_values: ['fabric', 'forge', 'neoforge'],
default_values: DEFAULT_MOD_LOADERS,
searchable: false,
options: tags.value.loaders
.filter(
@@ -357,7 +363,7 @@ export function useSearch(
supports_negative_filter: true,
searchable: false,
display: 'expandable',
default_values: ['iris', 'optifine', 'vanilla'],
default_values: DEFAULT_SHADER_LOADERS,
options: tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('shader'))
.map((loader) => {

View File

@@ -388,6 +388,29 @@ export const categoryMessages = defineMessages({
},
})
export const DEFAULT_MOD_LOADERS: string[] = ['fabric', 'forge', 'neoforge']
export const DEFAULT_SHADER_LOADERS: string[] = ['iris', 'optifine', 'vanilla']
const DEFAULT_LOADER_NAMES = new Set([...DEFAULT_MOD_LOADERS, ...DEFAULT_SHADER_LOADERS])
// sort by:
// 1. categories, alphabetically
// 2. default loaders, alphabetically
// 3. other loaders, alphabetically
export function sortTagsForDisplay(tags: string[]): string[] {
const isLoader = (tag: string) => getTagMessage(tag, 'loader') !== undefined
const loaders = tags.filter(isLoader)
const categories = tags.filter((tag) => !isLoader(tag))
categories.sort((a, b) => a.localeCompare(b))
loaders.sort((a, b) => {
const aDefault = DEFAULT_LOADER_NAMES.has(a)
const bDefault = DEFAULT_LOADER_NAMES.has(b)
if (aDefault !== bDefault) return aDefault ? -1 : 1
return a.localeCompare(b)
})
return [...categories, ...loaders]
}
export const categoryHeaderMessages = defineMessages({
resolutions: {
id: 'header.category.resolutions',