2020-06-29 11:56:46 +03:00
< template >
2025-08-14 21:48:38 +01:00
< div class = "pointer-events-none fixed inset-0 z-[-1]" >
< div id = "fixed-background-teleport" class = "relative" > < / div >
< / div >
< div class = "pointer-events-none absolute inset-0 z-[-1]" >
< div id = "absolute-background-teleport" class = "relative" > < / div >
< / div >
< div class = "pointer-events-none absolute inset-0 z-50" >
< div
class = "over-the-top-random-animation"
: style = "{ '--_r-count': rCount }"
: class = "{ threshold: rCount > 20, 'rings-expand': rCount >= 40 }"
>
< div >
< div
class = "animation-ring-3 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-40"
> < / div >
< div
class = "animation-ring-2 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight opacity-60"
> < / div >
< div
class = "animation-ring-1 flex items-center justify-center rounded-full border-4 border-solid border-brand bg-brand-highlight text-9xl font-extrabold text-contrast"
>
?
< / div >
< / div >
< / div >
< / div >
2025-11-07 08:47:54 -08:00
< div
ref = "main_page"
class = "layout"
: class = " {
'expanded-mobile-nav' : isBrowseMenuOpen ,
'modrinth-parent__no-modal-blurs' : ! cosmetics . advancedRendering ,
} "
>
2025-10-01 19:00:01 -07:00
< PagewideBanner v-if = "isRussia && !flags.hideRussiaCensorshipBanner" variant="error" >
< template # title >
< div class = "flex flex-col gap-1 text-contrast" >
< span lang = "ru" > К сожалению , Modrinth скоро станет недоступен в России < / span >
< span class = "text-sm font-medium opacity-50" lang = "en" >
Modrinth will soon be unavailable in Russia
< / span >
< / div >
< / template >
< template # description >
< p class = "m-0" lang = "ru" >
Российское правительство потребовало от нас заблокировать некоторые проекты на Modrinth ,
но мы решили отказать им в цензуре .
< / p >
< p class = "-mt-2 mb-0 text-sm opacity-50" lang = "en" >
The Russian government has asked us to censor certain topics on Modrinth and we have
decided to refuse to comply with their requests .
< / p >
< p class = "m-0 font-semibold" lang = "ru" >
Пожалуйста , найдите какой - нибудь надёжный VPN или прокси , чтобы не потерять доступ к
Modrinth .
< / p >
< p class = "-mt-2 mb-0 text-sm opacity-50" lang = "en" >
Please seek a reputable VPN or proxy of some kind to continue to access Modrinth in
Russia .
< / p >
< / template >
< template # actions >
< div class = "mt-2 flex w-fit gap-2" >
< ButtonStyled color = "brand" >
< nuxt-link to = "/news/article/standing-by-our-values-russian" >
< BookTextIcon / > Прочесть наше полное заявление
< span class = "text-xs font-medium" > ( Перевод на русский ) < / span >
< / nuxt-link >
< / ButtonStyled >
< ButtonStyled >
< nuxt-link to = "/news/article/standing-by-our-values" >
< BookTextIcon / > Read our full statement
< span class = "text-xs font-medium" > ( English ) < / span >
< / nuxt-link >
< / ButtonStyled >
< / div >
< / template >
< template # actions_right >
< ButtonStyled circular type = "transparent" >
< button
v - tooltip = "formatMessage(commonMessages.closeButton)"
@ click = "hideRussiaCensorshipBanner"
>
< XIcon :aria-label = "formatMessage(commonMessages.closeButton)" / >
< / button >
< / ButtonStyled >
< / template >
< / PagewideBanner >
2025-10-19 22:03:21 +01:00
< PagewideBanner v-if = "showTinMismatchBanner" variant="error" >
< template # title >
< span > { { formatMessage ( tinMismatchBannerMessages . title ) } } < / span >
< / template >
< template # description >
< span > { { formatMessage ( tinMismatchBannerMessages . description ) } } < / span >
< / template >
< template # actions >
< div class = "flex w-fit flex-row" >
< ButtonStyled color = "red" >
< nuxt-link to = "https://support.modrinth.com" target = "_blank" rel = "noopener" >
< MessageIcon / > { { formatMessage ( tinMismatchBannerMessages . action ) } }
< / nuxt-link >
< / ButtonStyled >
< / div >
< / template >
< / PagewideBanner >
2025-09-21 23:23:07 +01:00
< PagewideBanner v-if = "showTaxComplianceBanner" variant="warning" >
< template # title >
< span > { { formatMessage ( taxBannerMessages . title ) } } < / span >
< / template >
< template # description >
< span > { { formatMessage ( taxBannerMessages . description ) } } < / span >
< / template >
< template # actions >
< ButtonStyled color = "orange" >
< button @click ="openTaxForm" >
< FileTextIcon / > { { formatMessage ( taxBannerMessages . action ) } }
< / button >
< / ButtonStyled >
< / template >
< / PagewideBanner >
2025-08-14 21:48:38 +01:00
< PagewideBanner
v - if = "auth.user && !auth.user.email_verified && route.path !== '/auth/verify-email'"
variant = "warning"
>
< template # title >
< span >
{ {
auth ? . user ? . email
? formatMessage ( verifyEmailBannerMessages . title )
: formatMessage ( addEmailBannerMessages . title )
} }
< / span >
< / template >
< template # description >
< span >
{ {
auth ? . user ? . email
? formatMessage ( verifyEmailBannerMessages . description )
: formatMessage ( addEmailBannerMessages . description )
} }
< / span >
< / template >
< template # actions >
2025-08-15 19:02:55 +01:00
< button v-if = "auth?.user?.email" class="btn" @click="handleResendEmailVerification" >
2025-08-14 21:48:38 +01:00
{ { formatMessage ( verifyEmailBannerMessages . action ) } }
< / button >
< nuxt-link v-else class = "btn" to = "/settings/account" >
< SettingsIcon aria -hidden = " true " / >
{ { formatMessage ( addEmailBannerMessages . action ) } }
< / nuxt-link >
< / template >
< / PagewideBanner >
< PagewideBanner
v - if = "
user . subscriptions . some ( ( x ) => x . status === 'payment-failed' ) &&
route . path !== '/settings/billing'
"
variant = "error"
>
< template # title >
< span > { { formatMessage ( subscriptionPaymentFailedBannerMessages . title ) } } < / span >
< / template >
< template # description >
< span > { { formatMessage ( subscriptionPaymentFailedBannerMessages . description ) } } < / span >
< / template >
< template # actions >
< nuxt-link class = "btn" to = "/settings/billing" >
< SettingsIcon aria -hidden = " true " / >
{ { formatMessage ( subscriptionPaymentFailedBannerMessages . action ) } }
< / nuxt-link >
< / template >
< / PagewideBanner >
< PagewideBanner
v - if = "
config . public . apiBaseUrl . startsWith ( 'https://staging-api.modrinth.com' ) &&
! cosmetics . hideStagingBanner
"
variant = "warning"
>
< template # title >
< span > { { formatMessage ( stagingBannerMessages . title ) } } < / span >
< / template >
< template # description >
{ { formatMessage ( stagingBannerMessages . description ) } }
< / template >
< template # actions_right >
2025-09-15 00:49:31 -07:00
< Button
transparent
icon - only
2025-10-01 19:00:01 -07:00
: aria - label = "formatMessage(commonMessages.closeButton)"
2025-09-15 00:49:31 -07:00
@ click = "hideStagingBanner"
>
2025-08-14 21:48:38 +01:00
< XIcon aria -hidden = " true " / >
< / Button >
< / template >
< / PagewideBanner >
< PagewideBanner v-if = "generatedStateErrors?.length" variant="error" >
< template # title >
< span > { { formatMessage ( failedToBuildBannerMessages . title ) } } < / span >
< / template >
< template # description >
{ {
formatMessage ( failedToBuildBannerMessages . description , {
2025-11-28 12:11:39 -08:00
errors : JSON . stringify ( generatedStateErrors ) ,
2025-08-14 21:48:38 +01:00
url : config . public . apiBaseUrl ,
} )
} }
< / template >
< / PagewideBanner >
2025-09-21 23:23:07 +01:00
< CreatorTaxFormModal
ref = "taxFormModalRef"
2025-10-07 22:51:43 +01:00
close - button - text = "Close"
: emit - success - on - close = "false"
2025-09-21 23:23:07 +01:00
/ >
2025-08-14 21:48:38 +01:00
< header
class = "experimental-styles-within desktop-only relative z-[5] mx-auto grid max-w-[1280px] grid-cols-[1fr_auto] items-center gap-2 px-6 py-4 lg:grid-cols-[auto_1fr_auto]"
>
< div >
2025-11-13 15:21:43 -08:00
< NuxtLink
to = "/"
: aria - label = "formatMessage(messages.modrinthHomePage)"
class = "group hover:brightness-[--hover-brightness] focus-visible:brightness-[--hover-brightness]"
>
< TextLogo
aria - hidden = "true"
class = "h-7 w-auto text-contrast transition-transform group-active:scale-[0.98]"
/ >
2025-08-14 21:48:38 +01:00
< / NuxtLink >
< / div >
< div
: class = "`col-span-2 row-start-2 flex flex-wrap justify-center ${flags.projectTypesPrimaryNav ? 'gap-2' : 'gap-4'} lg:col-span-1 lg:row-start-auto`"
>
< template v-if = "flags.projectTypesPrimaryNav" >
< ButtonStyled
type = "transparent"
: highlighted = "route.name === 'search-mods' || route.path.startsWith('/mod/')"
: highlighted - style = "
route . name === 'search-mods' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
2025-09-15 00:49:31 -07:00
< nuxt-link to = "/mods" >
< BoxIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . mod ) } }
< / nuxt-link >
2025-08-14 21:48:38 +01:00
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "
route . name === 'search-resourcepacks' || route . path . startsWith ( '/resourcepack/' )
"
: highlighted - style = "
route . name === 'search-resourcepacks' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
< nuxt-link to = "/resourcepacks" >
2025-09-15 00:49:31 -07:00
< PaintbrushIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . resourcepack ) } }
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "route.name === 'search-datapacks' || route.path.startsWith('/datapack/')"
: highlighted - style = "
route . name === 'search-datapacks' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
2025-09-15 00:49:31 -07:00
< nuxt-link to = "/datapacks" >
< BracesIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . datapack ) } }
< / nuxt-link >
2025-08-14 21:48:38 +01:00
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "route.name === 'search-modpacks' || route.path.startsWith('/modpack/')"
: highlighted - style = "
route . name === 'search-modpacks' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
2025-09-15 00:49:31 -07:00
< nuxt-link to = "/modpacks" >
< PackageOpenIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . modpack ) } }
< / nuxt-link >
2025-08-14 21:48:38 +01:00
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "route.name === 'search-shaders' || route.path.startsWith('/shader/')"
: highlighted - style = "
route . name === 'search-shaders' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
2025-09-15 00:49:31 -07:00
< nuxt-link to = "/shaders" >
< GlassesIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . shader ) } }
< / nuxt-link >
2025-08-14 21:48:38 +01:00
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "route.name === 'search-plugins' || route.path.startsWith('/plugin/')"
: highlighted - style = "
route . name === 'search-plugins' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
2025-09-15 00:49:31 -07:00
< nuxt-link to = "/plugins" >
< PlugIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . plugin ) } }
< / nuxt-link >
2025-08-14 21:48:38 +01:00
< / ButtonStyled >
< / template >
< template v-else >
< ButtonStyled
type = "transparent"
: highlighted = "isDiscovering || isDiscoveringSubpage"
: highlighted - style = "isDiscoveringSubpage ? 'main-nav-secondary' : 'main-nav-primary'"
>
< TeleportOverflowMenu
: options = " [
{
id : 'mods' ,
action : '/mods' ,
} ,
{
id : 'resourcepacks' ,
action : '/resourcepacks' ,
} ,
{
id : 'datapacks' ,
action : '/datapacks' ,
} ,
{
id : 'shaders' ,
action : '/shaders' ,
} ,
{
id : 'modpacks' ,
action : '/modpacks' ,
} ,
{
id : 'plugins' ,
action : '/plugins' ,
} ,
] "
hoverable
>
< BoxIcon
v - if = "route.name === 'search-mods' || route.path.startsWith('/mod/')"
aria - hidden = "true"
/ >
< PaintbrushIcon
v - else - if = "
route . name === 'search-resourcepacks' || route . path . startsWith ( '/resourcepack/' )
"
aria - hidden = "true"
/ >
< BracesIcon
v - else - if = "route.name === 'search-datapacks' || route.path.startsWith('/datapack/')"
aria - hidden = "true"
/ >
< PackageOpenIcon
v - else - if = "route.name === 'search-modpacks' || route.path.startsWith('/modpack/')"
aria - hidden = "true"
/ >
< GlassesIcon
v - else - if = "route.name === 'search-shaders' || route.path.startsWith('/shader/')"
aria - hidden = "true"
/ >
< PlugIcon
v - else - if = "route.name === 'search-plugins' || route.path.startsWith('/plugin/')"
aria - hidden = "true"
/ >
< CompassIcon v-else aria -hidden = " true " / >
2025-09-15 00:49:31 -07:00
< span class = "hidden md:contents" > { {
formatMessage ( navMenuMessages . discoverContent )
} } < / span >
< span class = "contents md:hidden" > { { formatMessage ( navMenuMessages . discover ) } } < / span >
2025-11-13 15:21:43 -08:00
< DropdownIcon aria -hidden = " true " class = "h-5 w-5" / >
2025-08-14 21:48:38 +01:00
2025-09-15 00:49:31 -07:00
< template # mods >
< BoxIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . mod ) } }
< / template >
2025-08-14 21:48:38 +01:00
< template # resourcepacks >
2025-09-15 00:49:31 -07:00
< PaintbrushIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . resourcepack ) } }
< / template >
< template # datapacks >
< BracesIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . datapack ) } }
< / template >
< template # plugins >
< PlugIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . plugin ) } }
< / template >
< template # shaders >
< GlassesIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . shader ) } }
< / template >
< template # modpacks >
< PackageOpenIcon aria -hidden = " true " / >
{ { formatMessage ( commonProjectTypeCategoryMessages . modpack ) } }
2025-08-14 21:48:38 +01:00
< / template >
< / TeleportOverflowMenu >
< / ButtonStyled >
< ButtonStyled
type = "transparent"
: highlighted = "
route . name ? . startsWith ( 'servers' ) ||
( route . name ? . startsWith ( 'search-' ) && route . query . sid )
"
: highlighted - style = "
route . name === 'servers' ? 'main-nav-primary' : 'main-nav-secondary'
"
>
< nuxt-link to = "/servers" >
< ServerIcon aria -hidden = " true " / >
2025-09-15 00:49:31 -07:00
{ { formatMessage ( navMenuMessages . hostAServer ) } }
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / ButtonStyled >
< ButtonStyled type = "transparent" : highlighted = "route.name === 'app'" >
< nuxt-link to = "/app" >
< DownloadIcon aria -hidden = " true " / >
2025-09-15 00:49:31 -07:00
< span class = "hidden md:contents" > { {
formatMessage ( navMenuMessages . getModrinthApp )
} } < / span >
< span class = "contents md:hidden" > { {
formatMessage ( navMenuMessages . modrinthApp )
} } < / span >
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / ButtonStyled >
< / template >
< / div >
< div class = "flex items-center gap-1" >
< ButtonStyled type = "transparent" >
< OverflowMenu
v - if = "auth.user && isStaff(auth.user)"
class = "btn-dropdown-animation flex items-center gap-1 rounded-xl bg-transparent px-2 py-1"
position = "bottom"
direction = "left"
: dropdown - id = "`${basePopoutId}-staff`"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(messages.createNew)"
2025-08-14 21:48:38 +01:00
: options = " [
{
id : 'review-projects' ,
color : 'orange' ,
link : '/moderation/' ,
} ,
{
id : 'review-reports' ,
color : 'orange' ,
link : '/moderation/reports' ,
} ,
2025-08-28 14:52:43 -07:00
{
divider : true ,
} ,
{
id : 'file-lookup' ,
link : '/admin/file_lookup' ,
} ,
2025-08-14 21:48:38 +01:00
{
divider : true ,
shown : isAdmin ( auth . user ) ,
} ,
{
id : 'user-lookup' ,
color : 'primary' ,
link : '/admin/user_email' ,
shown : isAdmin ( auth . user ) ,
} ,
2025-11-02 11:32:18 -08:00
{
id : 'affiliates' ,
color : 'primary' ,
link : '/admin/affiliates' ,
shown : isAdmin ( auth . user ) ,
} ,
2025-08-14 21:48:38 +01:00
{
id : 'servers-notices' ,
color : 'primary' ,
link : '/admin/servers/notices' ,
shown : isAdmin ( auth . user ) ,
} ,
2025-10-20 18:35:44 +01:00
{
id : 'servers-nodes' ,
color : 'primary' ,
2025-11-12 04:14:11 +00:00
action : ( event ) => $refs . modal _batch _credit . show ( event ) ,
2025-10-20 18:35:44 +01:00
shown : isAdmin ( auth . user ) ,
} ,
2025-08-14 21:48:38 +01:00
] "
>
< ModrinthIcon aria -hidden = " true " / >
< DropdownIcon aria -hidden = " true " class = "h-5 w-5 text-secondary" / >
2025-09-15 00:49:31 -07:00
< template # review -projects >
< ScaleIcon aria -hidden = " true " / > { { formatMessage ( messages . reviewProjects ) } }
< / template >
< template # review -reports >
< ReportIcon aria -hidden = " true " / > { { formatMessage ( messages . reports ) } }
< / template >
< template # user -lookup >
2025-11-02 11:32:18 -08:00
< UserSearchIcon aria -hidden = " true " / > { { formatMessage ( messages . lookupByEmail ) } }
2025-09-15 00:49:31 -07:00
< / template >
< template # file -lookup >
< FileIcon aria -hidden = " true " / > { { formatMessage ( messages . fileLookup ) } }
< / template >
2025-08-14 21:48:38 +01:00
< template # servers -notices >
2025-09-15 00:49:31 -07:00
< IssuesIcon aria -hidden = " true " / > { { formatMessage ( messages . manageServerNotices ) } }
2025-08-14 21:48:38 +01:00
< / template >
2025-11-02 11:32:18 -08:00
< template # affiliates >
< AffiliateIcon aria -hidden = " true " / > { { formatMessage ( messages . manageAffiliates ) } }
< / template >
< template # servers -nodes >
< ServerIcon aria -hidden = " true " / > Credit server nodes
< / template >
2025-08-14 21:48:38 +01:00
< / OverflowMenu >
< / ButtonStyled >
< ButtonStyled type = "transparent" >
< OverflowMenu
v - if = "auth.user"
class = "btn-dropdown-animation flex items-center gap-1 rounded-xl bg-transparent px-2 py-1"
position = "bottom"
direction = "left"
: dropdown - id = "`${basePopoutId}-create`"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(messages.createNew)"
2025-08-14 21:48:38 +01:00
: options = " [
{
id : 'new-project' ,
action : ( event ) => $refs . modal _creation . show ( event ) ,
} ,
{
id : 'new-collection' ,
action : ( event ) => $refs . modal _collection _creation . show ( event ) ,
} ,
{ divider : true } ,
{
id : 'new-organization' ,
action : ( event ) => $refs . modal _organization _creation . show ( event ) ,
} ,
] "
>
< PlusIcon aria -hidden = " true " / >
< DropdownIcon aria -hidden = " true " class = "h-5 w-5 text-secondary" / >
2025-09-15 00:49:31 -07:00
< template # new -project >
< BoxIcon aria -hidden = " true " / > { { formatMessage ( messages . newProject ) } }
< / template >
2025-08-14 21:48:38 +01:00
<!-- < template # import -project > < BoxImportIcon / > Import project < / template > -- >
< template # new -collection >
2025-09-15 00:49:31 -07:00
< CollectionIcon aria -hidden = " true " / > { { formatMessage ( messages . newCollection ) } }
2025-08-14 21:48:38 +01:00
< / template >
< template # new -organization >
2025-09-15 00:49:31 -07:00
< OrganizationIcon aria -hidden = " true " / > { { formatMessage ( messages . newOrganization ) } }
2025-08-14 21:48:38 +01:00
< / template >
< / OverflowMenu >
< / ButtonStyled >
< OverflowMenu
v - if = "auth.user"
: dropdown - id = "`${basePopoutId}-user`"
class = "btn-dropdown-animation flex items-center gap-1 rounded-xl bg-transparent px-2 py-1"
: options = "userMenuOptions"
>
< Avatar :src = "auth.user.avatar_url" aria -hidden = " true " circle / >
< DropdownIcon class = "h-5 w-5 text-secondary" / >
2025-09-15 00:49:31 -07:00
< template # profile >
< UserIcon aria -hidden = " true " / > { { formatMessage ( messages . profile ) } }
< / template >
< template # notifications >
< BellIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . notificationsLabel ) } }
< / template >
2025-11-03 23:15:25 +00:00
< template # reports >
< ReportIcon aria -hidden = " true " / > { { formatMessage ( messages . activeReports ) } }
< / template >
2025-09-15 00:49:31 -07:00
< template # saved >
2025-11-03 23:15:25 +00:00
< LibraryIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . collectionsLabel ) } }
2025-09-15 00:49:31 -07:00
< / template >
< template # servers >
2025-11-03 23:15:25 +00:00
< ServerIcon aria -hidden = " true " / > { { formatMessage ( messages . myServers ) } }
2025-09-15 00:49:31 -07:00
< / template >
2025-08-14 21:48:38 +01:00
< template # plus >
2025-09-15 00:49:31 -07:00
< ArrowBigUpDashIcon aria -hidden = " true " / >
{ { formatMessage ( messages . upgradeToModrinthPlus ) } }
< / template >
< template # settings >
< SettingsIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . settingsLabel ) } }
< / template >
< template # flags >
< ReportIcon aria -hidden = " true " / > { { formatMessage ( messages . featureFlags ) } }
< / template >
< template # projects >
< BoxIcon aria -hidden = " true " / > { { formatMessage ( messages . projects ) } }
2025-08-14 21:48:38 +01:00
< / template >
< template # organizations >
2025-09-15 00:49:31 -07:00
< OrganizationIcon aria -hidden = " true " / > { { formatMessage ( messages . organizations ) } }
< / template >
2025-11-02 11:32:18 -08:00
< template # affiliate -links >
< AffiliateIcon aria -hidden = " true " / >
{ { formatMessage ( commonMessages . affiliateLinksButton ) } }
< / template >
2025-09-15 00:49:31 -07:00
< template # revenue >
< CurrencyIcon aria -hidden = " true " / > { { formatMessage ( messages . revenue ) } }
< / template >
< template # analytics >
< ChartIcon aria -hidden = " true " / > { { formatMessage ( messages . analytics ) } }
< / template >
< template # moderation >
< ScaleIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . moderationLabel ) } }
< / template >
< template # sign -out >
< LogOutIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . signOutButton ) } }
2025-08-14 21:48:38 +01:00
< / template >
< / OverflowMenu >
< template v-else >
< ButtonStyled color = "brand" >
< nuxt-link to = "/auth/sign-in" >
< LogInIcon aria -hidden = " true " / >
2025-09-15 00:49:31 -07:00
{ { formatMessage ( commonMessages . signInButton ) } }
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / ButtonStyled >
< ButtonStyled circular >
2025-09-15 00:49:31 -07:00
< nuxt-link :v-tooltip = "formatMessage(commonMessages.settingsLabel)" to = "/settings" >
< SettingsIcon :aria-label = "formatMessage(commonMessages.settingsLabel)" / >
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / ButtonStyled >
< / template >
< / div >
< / header >
< header class = "mobile-navigation mobile-only" >
< div
class = "nav-menu nav-menu-browse"
: class = "{ expanded: isBrowseMenuOpen }"
@ focusin = "isBrowseMenuOpen = true"
@ focusout = "isBrowseMenuOpen = false"
>
< div class = "links cascade-links" >
< NuxtLink
v - for = "navRoute in navRoutes"
: key = "navRoute.href"
: to = "navRoute.href"
class = "iconified-button"
>
{ { navRoute . label } }
< / NuxtLink >
< / div >
< / div >
< div
class = "nav-menu nav-menu-mobile"
: class = "{ expanded: isMobileMenuOpen }"
@ focusin = "isMobileMenuOpen = true"
@ focusout = "isMobileMenuOpen = false"
>
< div class = "account-container" >
< NuxtLink
v - if = "auth.user"
: to = "`/user/${auth.user.username}`"
class = "iconified-button account-button"
>
< Avatar
: src = "auth.user.avatar_url"
class = "user-icon"
: alt = "formatMessage(messages.yourAvatarAlt)"
aria - hidden = "true"
circle
/ >
< div class = "account-text" >
< div > @ { { auth . user . username } } < / div >
< div > { { formatMessage ( commonMessages . visitYourProfile ) } } < / div >
< / div >
< / NuxtLink >
< nuxt-link v-else class = "iconified-button brand-button" to = "/auth/sign-in" >
2025-08-17 12:15:49 +01:00
< LogInIcon aria -hidden = " true " / > { { formatMessage ( commonMessages . signInButton ) } }
2025-08-14 21:48:38 +01:00
< / nuxt-link >
< / div >
< div class = "links" >
< template v-if = "auth.user" >
< button class = "iconified-button danger-button" @click ="logoutUser()" >
< LogOutIcon aria -hidden = " true " / >
{ { formatMessage ( commonMessages . signOutButton ) } }
< / button >
< button class = "iconified-button" @click ="$refs.modal_creation.show()" >
< PlusIcon aria -hidden = " true " / >
{ { formatMessage ( commonMessages . createAProjectButton ) } }
< / button >
< NuxtLink class = "iconified-button" to = "/dashboard/collections" >
< LibraryIcon class = "icon" / >
{ { formatMessage ( commonMessages . collectionsLabel ) } }
< / NuxtLink >
< NuxtLink class = "iconified-button" to = "/servers/manage" >
< ServerIcon class = "icon" / >
{ { formatMessage ( commonMessages . serversLabel ) } }
< / NuxtLink >
< NuxtLink
v - if = "auth.user.role === 'moderator' || auth.user.role === 'admin'"
class = "iconified-button"
to = "/moderation"
>
< ScaleIcon aria -hidden = " true " / >
{ { formatMessage ( commonMessages . moderationLabel ) } }
< / NuxtLink >
< NuxtLink v-if = "flags.developerMode" class="iconified-button" to="/flags" >
< ReportIcon aria -hidden = " true " / >
2025-09-15 00:49:31 -07:00
{ { formatMessage ( messages . featureFlags ) } }
2025-08-14 21:48:38 +01:00
< / NuxtLink >
< / template >
< NuxtLink class = "iconified-button" to = "/settings" >
< SettingsIcon aria -hidden = " true " / >
{ { formatMessage ( commonMessages . settingsLabel ) } }
< / NuxtLink >
< button class = "iconified-button" @click ="changeTheme" >
< MoonIcon v-if = "$theme.active === 'light'" class="icon" / >
< SunIcon v-else class = "icon" / >
< span class = "dropdown-item__text" >
{ { formatMessage ( messages . changeTheme ) } }
< / span >
< / button >
< / div >
< / div >
< div class = "mobile-navbar" : class = "{ expanded: isBrowseMenuOpen || isMobileMenuOpen }" >
< NuxtLink
to = "/"
class = "tab button-animation"
: title = "formatMessage(navMenuMessages.home)"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(navMenuMessages.home)"
2025-08-14 21:48:38 +01:00
>
< HomeIcon aria -hidden = " true " / >
< / NuxtLink >
< button
class = "tab button-animation"
: class = "{ 'router-link-exact-active': isBrowseMenuOpen }"
: title = "formatMessage(navMenuMessages.search)"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(navMenuMessages.search)"
2025-08-14 21:48:38 +01:00
@ click = "toggleBrowseMenu()"
>
< template v-if = "auth.user" >
< SearchIcon aria -hidden = " true " / >
< / template >
< template v-else >
< SearchIcon aria -hidden = " true " class = "smaller" / >
{ { formatMessage ( navMenuMessages . search ) } }
< / template >
< / button >
< template v-if = "auth.user" >
< NuxtLink
to = "/dashboard/notifications"
class = "tab button-animation"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(commonMessages.notificationsLabel)"
2025-08-14 21:48:38 +01:00
: class = " {
'no-active' : isMobileMenuOpen || isBrowseMenuOpen ,
} "
: title = "formatMessage(commonMessages.notificationsLabel)"
@ click = "
( ) => {
isMobileMenuOpen = false
isBrowseMenuOpen = false
}
"
>
< BellIcon aria -hidden = " true " / >
< / NuxtLink >
< NuxtLink
to = "/dashboard"
class = "tab button-animation"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(commonMessages.dashboardLabel)"
2025-08-14 21:48:38 +01:00
: title = "formatMessage(commonMessages.dashboardLabel)"
>
< ChartIcon aria -hidden = " true " / >
< / NuxtLink >
< / template >
< button
class = "tab button-animation"
: title = "formatMessage(messages.toggleMenu)"
2025-11-03 23:15:25 +00:00
: aria - label = "
isMobileMenuOpen ? formatMessage ( messages . closeMenu ) : formatMessage ( messages . openMenu )
"
2025-08-14 21:48:38 +01:00
@ click = "toggleMobileMenu()"
>
< template v-if = "!auth.user" >
< HamburgerIcon v-if = "!isMobileMenuOpen" aria-hidden="true" / >
< XIcon v-else aria -hidden = " true " / >
< / template >
< template v-else >
< Avatar
: src = "auth.user.avatar_url"
class = "user-icon"
: class = "{ expanded: isMobileMenuOpen }"
: alt = "formatMessage(messages.yourAvatarAlt)"
aria - hidden = "true"
circle
/ >
< / template >
< / button >
< / div >
< / header >
< main class = "min-h-[calc(100vh-4.5rem-310.59px)]" >
2025-09-28 20:48:21 +01:00
< ProjectCreateModal v-if = "auth.user" ref="modal_creation" / >
2025-08-14 21:48:38 +01:00
< CollectionCreateModal ref = "modal_collection_creation" / >
< OrganizationCreateModal ref = "modal_organization_creation" / >
2025-11-12 04:14:11 +00:00
< BatchCreditModal v-if = "auth.user && isAdmin(auth.user)" ref="modal_batch_credit" / >
2025-08-14 21:48:38 +01:00
< slot id = "main" / >
< / main >
< footer
class = "footer-brand-background experimental-styles-within border-0 border-t-[1px] border-solid"
>
< div class = "mx-auto flex max-w-screen-xl flex-col gap-6 p-6 pb-20 sm:px-12 md:py-12" >
< div
class = "grid grid-cols-1 gap-4 text-primary md:grid-cols-[1fr_2fr] lg:grid-cols-[auto_auto_auto_auto_auto]"
>
< div
class = "flex flex-col items-center gap-3 md:items-start"
role = "region"
2025-09-15 00:49:31 -07:00
: aria - label = "formatMessage(messages.modrinthInformation)"
2025-08-14 21:48:38 +01:00
>
2025-08-17 12:15:49 +01:00
< TextLogo
2025-08-14 21:48:38 +01:00
aria - hidden = "true"
class = "text-logo button-base h-6 w-auto text-contrast lg:h-8"
@ click = "developerModeIncrement()"
/ >
< div class = "flex flex-wrap justify-center gap-px sm:-mx-2" >
< ButtonStyled
v - for = "(social, index) in socialLinks"
: key = "`footer-social-${index}`"
circular
type = "transparent"
>
< a
v - tooltip = "social.label"
: href = "social.href"
target = "_blank"
: rel = "`noopener${social.rel ? ` ${social.rel}` : ''}`"
>
< component :is = "social.icon" class = "h-5 w-5" / >
< / a >
< / ButtonStyled >
< / div >
< div class = "mt-auto flex flex-wrap justify-center gap-3 md:flex-col" >
< p class = "m-0" >
< IntlFormatted :message-id = "footerMessages.openSource" >
< template # github -link = " { children } " >
< a
href = "https://github.com/modrinth/code"
class = "text-brand hover:underline"
target = "_blank"
rel = "noopener"
>
< component : is = "() => children" / >
< / a >
< / template >
< / IntlFormatted >
< / p >
2025-11-03 23:15:25 +00:00
< p class = "m-0" >
{ { formatMessage ( footerMessages . copyright , { year : currentYear } ) } }
< / p >
2025-08-14 21:48:38 +01:00
< / div >
< / div >
< div class = "mt-4 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:contents" >
< div
v - for = "group in footerLinks"
: key = "group.label"
class = "flex flex-col items-center gap-3 sm:items-start"
>
< h3 class = "m-0 text-base text-contrast" > { { group . label } } < / h3 >
< template v-for = "item in group.links" :key="item.label" >
< nuxt-link
v - if = "item.href.startsWith('/')"
: to = "item.href"
class = "w-fit hover:underline"
>
{ { item . label } }
< / nuxt-link >
< a
v - else
: href = "item.href"
class = "w-fit hover:underline"
target = "_blank"
rel = "noopener"
>
{ { item . label } }
< / a >
< / template >
< / div >
< / div >
< / div >
< div class = "flex justify-center text-center text-xs font-medium text-secondary opacity-50" >
{ { formatMessage ( footerMessages . legalDisclaimer ) } }
< / div >
< / div >
< / footer >
< / div >
2020-06-29 11:56:46 +03:00
< / template >
2023-03-09 10:05:32 -07:00
< script setup >
2024-06-11 19:46:07 -07:00
import {
2025-11-02 11:32:18 -08:00
AffiliateIcon ,
2025-08-14 21:48:38 +01:00
ArrowBigUpDashIcon ,
BellIcon ,
BlueskyIcon ,
2025-10-01 19:00:01 -07:00
BookTextIcon ,
2025-08-14 21:48:38 +01:00
BoxIcon ,
BracesIcon ,
ChartIcon ,
CollectionIcon ,
CompassIcon ,
CurrencyIcon ,
DiscordIcon ,
DownloadIcon ,
DropdownIcon ,
2025-08-28 14:52:43 -07:00
FileIcon ,
2025-09-21 23:23:07 +01:00
FileTextIcon ,
2025-08-14 21:48:38 +01:00
GithubIcon ,
GlassesIcon ,
HamburgerIcon ,
HomeIcon ,
IssuesIcon ,
LibraryIcon ,
LogInIcon ,
LogOutIcon ,
MastodonIcon ,
2025-10-19 22:03:21 +01:00
MessageIcon ,
2025-08-14 21:48:38 +01:00
ModrinthIcon ,
MoonIcon ,
OrganizationIcon ,
PackageOpenIcon ,
PaintbrushIcon ,
PlugIcon ,
PlusIcon ,
ReportIcon ,
ScaleIcon ,
SearchIcon ,
ServerIcon ,
SettingsIcon ,
SunIcon ,
TwitterIcon ,
UserIcon ,
2025-11-02 11:32:18 -08:00
UserSearchIcon ,
2025-08-14 21:48:38 +01:00
XIcon ,
} from '@modrinth/assets'
2025-05-16 11:12:34 +01:00
import {
2025-08-14 21:48:38 +01:00
Avatar ,
Button ,
ButtonStyled ,
commonMessages ,
2025-09-15 00:49:31 -07:00
commonProjectTypeCategoryMessages ,
2025-08-14 21:48:38 +01:00
injectNotificationManager ,
OverflowMenu ,
PagewideBanner ,
} from '@modrinth/ui'
2025-11-02 11:32:18 -08:00
import { isAdmin , isStaff , UserBadge } from '@modrinth/utils'
2025-08-17 12:15:49 +01:00
import { IntlFormatted } from '@vintl/vintl/components'
2025-08-14 21:48:38 +01:00
2025-08-17 12:15:49 +01:00
import TextLogo from '~/components/brand/TextLogo.vue'
2025-11-12 04:14:11 +00:00
import BatchCreditModal from '~/components/ui/admin/BatchCreditModal.vue'
2025-09-28 20:48:21 +01:00
import CollectionCreateModal from '~/components/ui/create/CollectionCreateModal.vue'
import OrganizationCreateModal from '~/components/ui/create/OrganizationCreateModal.vue'
import ProjectCreateModal from '~/components/ui/create/ProjectCreateModal.vue'
2025-09-21 23:23:07 +01:00
import CreatorTaxFormModal from '~/components/ui/dashboard/CreatorTaxFormModal.vue'
2025-08-14 21:48:38 +01:00
import TeleportOverflowMenu from '~/components/ui/servers/TeleportOverflowMenu.vue'
import { errors as generatedStateErrors } from '~/generated/state.json'
import { getProjectTypeMessage } from '~/utils/i18n-project-type.ts'
2025-10-01 19:00:01 -07:00
const country = useUserCountry ( )
2025-08-14 21:48:38 +01:00
const { formatMessage } = useVIntl ( )
const auth = await useAuth ( )
const user = await useUser ( )
2025-08-17 12:15:49 +01:00
const { addNotification } = injectNotificationManager ( )
2025-08-14 21:48:38 +01:00
const cosmetics = useCosmetics ( )
const flags = useFeatureFlags ( )
const config = useRuntimeConfig ( )
const route = useNativeRoute ( )
const router = useNativeRouter ( )
const link = config . public . siteUrl + route . path . replace ( /\/+$/ , '' )
2025-09-21 23:23:07 +01:00
const { data : payoutBalance } = await useAsyncData ( 'payout/balance' , ( ) =>
useBaseFetch ( 'payout/balance' , { apiVersion : 3 } ) ,
)
const showTaxComplianceBanner = computed ( ( ) => {
2025-10-07 22:51:43 +01:00
if ( flags . value . testTaxForm && auth . value . user ) return true
2025-09-21 23:23:07 +01:00
const bal = payoutBalance . value
if ( ! bal ) return false
const thresholdMet = ( bal . withdrawn _ytd ? ? 0 ) >= 600
const status = bal . form _completion _status ? ? 'unknown'
const isComplete = status === 'complete'
2025-10-19 22:03:21 +01:00
const isTinMismatch = status === 'tin-mismatch'
return ! ! auth . value . user && thresholdMet && ! isComplete && ! isTinMismatch
} )
const showTinMismatchBanner = computed ( ( ) => {
const bal = payoutBalance . value
if ( ! bal ) return false
const status = bal . form _completion _status ? ? 'unknown'
return ! ! auth . value . user && status === 'tin-mismatch'
2025-09-21 23:23:07 +01:00
} )
const taxBannerMessages = defineMessages ( {
title : {
id : 'layout.banner.tax.title' ,
defaultMessage : 'Tax form required' ,
} ,
description : {
id : 'layout.banner.tax.description' ,
defaultMessage :
2025-10-19 22:03:21 +01:00
"You've already withdrawn over $600 from Modrinth this year. To comply with tax regulations, you need to complete a tax form. Your withdrawals are paused until this form is submitted." ,
2025-09-21 23:23:07 +01:00
} ,
action : {
id : 'layout.banner.tax.action' ,
defaultMessage : 'Complete tax form' ,
} ,
} )
2025-10-19 22:03:21 +01:00
const tinMismatchBannerMessages = defineMessages ( {
title : {
id : 'layout.banner.tin-mismatch.title' ,
defaultMessage : 'Tax form failed' ,
} ,
description : {
id : 'layout.banner.tin-mismatch.description' ,
defaultMessage :
"Your withdrawals are temporarily locked because your TIN or SSN didn't match IRS records. Please contact support to reset and resubmit your tax form." ,
} ,
action : {
id : 'layout.banner.tin-mismatch.action' ,
defaultMessage : 'Contact support' ,
} ,
} )
2025-09-21 23:23:07 +01:00
const taxFormModalRef = ref ( null )
function openTaxForm ( e ) {
if ( taxFormModalRef . value && taxFormModalRef . value . startTaxForm ) {
taxFormModalRef . value . startTaxForm ( e )
}
}
2025-08-14 21:48:38 +01:00
const basePopoutId = useId ( )
2025-08-17 12:15:49 +01:00
async function handleResendEmailVerification ( ) {
try {
await resendVerifyEmail ( )
addNotification ( {
title : 'Verification email sent' ,
text : 'Please check your inbox for the verification email.' ,
type : 'success' ,
} )
} catch ( err ) {
addNotification ( {
title : 'An error occurred' ,
text : err . data . description ,
type : 'error' ,
} )
}
}
App redesign (#2946)
* Start of app redesign
* format
* continue progress
* Content page nearly done
* Fix recursion issues with content page
* Fix update all alignment
* Discover page progress
* Settings progress
* Removed unlocked-size hack that breaks web
* Revamp project page, refactor web project page to share code with app, fixed loading bar, misc UI/UX enhancements, update ko-fi logo, update arrow icons, fix web issues caused by floating-vue migration, fix tooltip issues, update web tooltips, clean up web hydration issues
* Ads + run prettier
* Begin auth refactor, move common messages to ui lib, add i18n extraction to all apps, begin Library refactor
* fix ads not hiding when plus log in
* rev lockfile changes/conflicts
* Fix sign in page
* Add generated
* (mostly) Data driven search
* Fix search mobile issue
* profile fixes
* Project versions page, fix typescript on UI lib and misc fixes
* Remove unused gallery component
* Fix linkfunction err
* Search filter controls at top, localization for locked filters
* Fix provided filter names
* Fix navigating from instance browse to main browse
* Friends frontend (#2995)
* Friends system frontend
* (almost) finish frontend
* finish friends, fix lint
* Fix lint
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
* Refresh macOS app icon
* Update web search UI more
* Fix link opens
* Fix frontend build
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
2024-12-11 19:54:18 -08:00
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const verifyEmailBannerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
title : {
id : 'layout.banner.account-action' ,
defaultMessage : 'Account action required' ,
} ,
description : {
id : 'layout.banner.verify-email.description' ,
defaultMessage :
'For security reasons, Modrinth needs you to verify the email address associated with your account.' ,
} ,
action : {
id : 'layout.banner.verify-email.action' ,
defaultMessage : 'Re-send verification email' ,
} ,
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const addEmailBannerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
title : {
id : 'layout.banner.account-action' ,
defaultMessage : 'Account action required' ,
} ,
description : {
id : 'layout.banner.add-email.description' ,
defaultMessage :
'For security reasons, Modrinth needs you to register an email address to your account.' ,
} ,
action : {
id : 'layout.banner.add-email.button' ,
defaultMessage : 'Visit account settings' ,
} ,
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2024-08-15 23:21:30 -07:00
const subscriptionPaymentFailedBannerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
title : {
id : 'layout.banner.subscription-payment-failed.title' ,
defaultMessage : 'Billing action required.' ,
} ,
description : {
id : 'layout.banner.subscription-payment-failed.description' ,
defaultMessage :
'One or more subscriptions failed to renew. Please update your payment method to prevent losing access!' ,
} ,
action : {
id : 'layout.banner.subscription-payment-failed.button' ,
defaultMessage : 'Update billing info' ,
} ,
} )
2024-08-15 23:21:30 -07:00
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const stagingBannerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
title : {
id : 'layout.banner.staging.title' ,
defaultMessage : 'You’ re viewing Modrinth’ s staging environment' ,
} ,
description : {
id : 'layout.banner.staging.description' ,
defaultMessage :
'The staging environment is completely separate from the production Modrinth database. This is used for testing and debugging purposes, and may be running in-development versions of the Modrinth backend or frontend newer than the production instance.' ,
} ,
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2025-03-18 18:26:57 -07:00
const failedToBuildBannerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
title : {
id : 'layout.banner.build-fail.title' ,
defaultMessage : 'Error generating state from API when building.' ,
} ,
description : {
id : 'layout.banner.build-fail.description' ,
defaultMessage :
"This deploy of Modrinth's frontend failed to generate state from the API. This may be due to an outage or an error in configuration. Rebuild when the API is available. Error codes: {errors}; Current API URL is: {url}" ,
} ,
} )
2025-03-18 18:26:57 -07:00
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const navMenuMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
home : {
id : 'layout.nav.home' ,
defaultMessage : 'Home' ,
} ,
search : {
id : 'layout.nav.search' ,
defaultMessage : 'Search' ,
} ,
2025-09-15 00:49:31 -07:00
discoverContent : {
id : 'layout.nav.discover-content' ,
defaultMessage : 'Discover content' ,
} ,
discover : {
id : 'layout.nav.discover' ,
defaultMessage : 'Discover' ,
} ,
hostAServer : {
id : 'layout.nav.host-a-server' ,
defaultMessage : 'Host a server' ,
} ,
getModrinthApp : {
id : 'layout.nav.get-modrinth-app' ,
defaultMessage : 'Get Modrinth App' ,
} ,
modrinthApp : {
id : 'layout.nav.modrinth-app' ,
defaultMessage : 'Modrinth App' ,
} ,
2025-08-14 21:48:38 +01:00
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const messages = defineMessages ( {
2025-08-14 21:48:38 +01:00
toggleMenu : {
id : 'layout.menu-toggle.action' ,
defaultMessage : 'Toggle menu' ,
} ,
yourAvatarAlt : {
id : 'layout.avatar.alt' ,
defaultMessage : 'Your avatar' ,
} ,
changeTheme : {
id : 'layout.action.change-theme' ,
defaultMessage : 'Change theme' ,
} ,
2025-09-15 00:49:31 -07:00
modrinthHomePage : {
id : 'layout.nav.modrinth-home-page' ,
defaultMessage : 'Modrinth home page' ,
} ,
modrinthInformation : {
id : 'layout.footer.modrinth-information' ,
defaultMessage : 'Modrinth information' ,
} ,
createNew : {
id : 'layout.action.create-new' ,
defaultMessage : 'Create new...' ,
} ,
reviewProjects : {
id : 'layout.action.review-projects' ,
defaultMessage : 'Review projects' ,
} ,
reports : {
id : 'layout.action.reports' ,
defaultMessage : 'Reports' ,
} ,
lookupByEmail : {
id : 'layout.action.lookup-by-email' ,
defaultMessage : 'Lookup by email' ,
} ,
fileLookup : {
id : 'layout.action.file-lookup' ,
defaultMessage : 'File lookup' ,
} ,
manageServerNotices : {
id : 'layout.action.manage-server-notices' ,
defaultMessage : 'Manage server notices' ,
} ,
2025-11-02 11:32:18 -08:00
manageAffiliates : {
id : 'layout.action.manage-affiliates' ,
defaultMessage : 'Manage affiliate links' ,
} ,
2025-09-15 00:49:31 -07:00
newProject : {
id : 'layout.action.new-project' ,
defaultMessage : 'New project' ,
} ,
newCollection : {
id : 'layout.action.new-collection' ,
defaultMessage : 'New collection' ,
} ,
newOrganization : {
id : 'layout.action.new-organization' ,
defaultMessage : 'New organization' ,
} ,
profile : {
id : 'layout.nav.profile' ,
defaultMessage : 'Profile' ,
} ,
savedProjects : {
id : 'layout.nav.saved-projects' ,
defaultMessage : 'Saved projects' ,
} ,
upgradeToModrinthPlus : {
id : 'layout.nav.upgrade-to-modrinth-plus' ,
defaultMessage : 'Upgrade to Modrinth+' ,
} ,
featureFlags : {
id : 'layout.nav.feature-flags' ,
defaultMessage : 'Feature flags' ,
} ,
projects : {
id : 'layout.nav.projects' ,
defaultMessage : 'Projects' ,
} ,
organizations : {
id : 'layout.nav.organizations' ,
defaultMessage : 'Organizations' ,
} ,
revenue : {
id : 'layout.nav.revenue' ,
defaultMessage : 'Revenue' ,
} ,
analytics : {
id : 'layout.nav.analytics' ,
defaultMessage : 'Analytics' ,
} ,
2025-11-03 23:15:25 +00:00
activeReports : {
id : 'layout.nav.active-reports' ,
defaultMessage : 'Active reports' ,
} ,
myServers : {
id : 'layout.nav.my-servers' ,
defaultMessage : 'My servers' ,
} ,
openMenu : {
id : 'layout.mobile.open-menu' ,
defaultMessage : 'Open menu' ,
} ,
closeMenu : {
id : 'layout.mobile.close-menu' ,
defaultMessage : 'Close menu' ,
} ,
2025-08-14 21:48:38 +01:00
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const footerMessages = defineMessages ( {
2025-08-14 21:48:38 +01:00
openSource : {
id : 'layout.footer.open-source' ,
defaultMessage : 'Modrinth is <github-link>open source</github-link>.' ,
} ,
legalDisclaimer : {
id : 'layout.footer.legal-disclaimer' ,
defaultMessage :
'NOT AN OFFICIAL MINECRAFT SERVICE. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.' ,
} ,
2025-11-03 23:15:25 +00:00
copyright : {
id : 'layout.footer.copyright' ,
defaultMessage : '© {year} Rinth, Inc.' ,
} ,
2025-08-14 21:48:38 +01:00
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2023-03-09 10:05:32 -07:00
useHead ( {
2025-08-14 21:48:38 +01:00
link : [
{
rel : 'canonical' ,
href : link ,
} ,
] ,
} )
2023-09-22 12:45:03 -04:00
useSeoMeta ( {
2025-08-14 21:48:38 +01:00
title : 'Modrinth' ,
description : ( ) =>
formatMessage ( {
id : 'layout.meta.description' ,
defaultMessage :
'Download Minecraft mods, plugins, datapacks, shaders, resourcepacks, and modpacks on Modrinth. ' +
'Discover and publish projects on Modrinth with a modern, easy to use interface and API.' ,
} ) ,
publisher : 'Modrinth' ,
themeColor : '#1bd96a' ,
colorScheme : 'dark light' ,
// OpenGraph
ogTitle : 'Modrinth' ,
ogSiteName : 'Modrinth' ,
ogDescription : ( ) =>
formatMessage ( {
id : 'layout.meta.og-description' ,
defaultMessage : 'Discover and publish Minecraft content!' ,
} ) ,
ogType : 'website' ,
ogImage : 'https://cdn.modrinth.com/modrinth-new.png' ,
ogUrl : link ,
// Twitter
twitterCard : 'summary' ,
twitterSite : '@modrinth' ,
} )
const developerModeCounter = ref ( 0 )
2025-11-03 23:15:25 +00:00
const currentYear = new Date ( ) . getFullYear ( )
2025-08-14 21:48:38 +01:00
const isMobileMenuOpen = ref ( false )
const isBrowseMenuOpen = ref ( false )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
const navRoutes = computed ( ( ) => [
2025-08-14 21:48:38 +01:00
{
id : 'mods' ,
label : formatMessage ( getProjectTypeMessage ( 'mod' , true ) ) ,
href : '/mods' ,
} ,
{
label : formatMessage ( getProjectTypeMessage ( 'plugin' , true ) ) ,
href : '/plugins' ,
} ,
{
label : formatMessage ( getProjectTypeMessage ( 'datapack' , true ) ) ,
href : '/datapacks' ,
} ,
{
label : formatMessage ( getProjectTypeMessage ( 'shader' , true ) ) ,
href : '/shaders' ,
} ,
{
label : formatMessage ( getProjectTypeMessage ( 'resourcepack' , true ) ) ,
href : '/resourcepacks' ,
} ,
{
label : formatMessage ( getProjectTypeMessage ( 'modpack' , true ) ) ,
href : '/modpacks' ,
} ,
] )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
const userMenuOptions = computed ( ( ) => {
2025-08-14 21:48:38 +01:00
let options = [
{
id : 'profile' ,
link : ` /user/ ${ auth . value . user . username } ` ,
} ,
{
id : 'plus' ,
link : '/plus' ,
color : 'purple' ,
shown : ! flags . value . hidePlusPromoInUserMenu && ! isPermission ( auth . value . user . badges , 1 << 0 ) ,
} ,
{
id : 'servers' ,
link : '/servers/manage' ,
} ,
{
id : 'flags' ,
link : '/flags' ,
shown : flags . value . developerMode ,
} ,
{
id : 'settings' ,
link : '/settings' ,
} ,
]
// TODO: Only show if user has projects
options = [
... options ,
{
divider : true ,
} ,
2025-11-03 23:15:25 +00:00
{
id : 'notifications' ,
link : '/dashboard/notifications' ,
} ,
{
id : 'reports' ,
link : '/dashboard/reports' ,
} ,
{
id : 'saved' ,
link : '/dashboard/collections' ,
} ,
{
divider : true ,
} ,
2025-08-14 21:48:38 +01:00
{
id : 'projects' ,
link : '/dashboard/projects' ,
} ,
{
id : 'organizations' ,
link : '/dashboard/organizations' ,
} ,
2025-11-03 23:15:25 +00:00
{
id : 'analytics' ,
link : '/dashboard/analytics' ,
} ,
2025-11-02 11:32:18 -08:00
{
id : 'affiliate-links' ,
link : '/dashboard/affiliate-links' ,
shown : auth . value . user . badges & UserBadge . AFFILIATE ,
} ,
2025-08-14 21:48:38 +01:00
{
id : 'revenue' ,
link : '/dashboard/revenue' ,
} ,
]
options = [
... options ,
{
divider : true ,
} ,
{
id : 'sign-out' ,
color : 'danger' ,
action : ( ) => logoutUser ( ) ,
hoverFilled : true ,
} ,
]
return options
} )
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
App redesign (#2946)
* Start of app redesign
* format
* continue progress
* Content page nearly done
* Fix recursion issues with content page
* Fix update all alignment
* Discover page progress
* Settings progress
* Removed unlocked-size hack that breaks web
* Revamp project page, refactor web project page to share code with app, fixed loading bar, misc UI/UX enhancements, update ko-fi logo, update arrow icons, fix web issues caused by floating-vue migration, fix tooltip issues, update web tooltips, clean up web hydration issues
* Ads + run prettier
* Begin auth refactor, move common messages to ui lib, add i18n extraction to all apps, begin Library refactor
* fix ads not hiding when plus log in
* rev lockfile changes/conflicts
* Fix sign in page
* Add generated
* (mostly) Data driven search
* Fix search mobile issue
* profile fixes
* Project versions page, fix typescript on UI lib and misc fixes
* Remove unused gallery component
* Fix linkfunction err
* Search filter controls at top, localization for locked filters
* Fix provided filter names
* Fix navigating from instance browse to main browse
* Friends frontend (#2995)
* Friends system frontend
* (almost) finish frontend
* finish friends, fix lint
* Fix lint
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
* Refresh macOS app icon
* Update web search UI more
* Fix link opens
* Fix frontend build
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
2024-12-11 19:54:18 -08:00
const isDiscovering = computed (
2025-08-14 21:48:38 +01:00
( ) => route . name && route . name . startsWith ( 'search-' ) && ! route . query . sid ,
)
Pyro Integration (#2503)
* fix
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor(fileitem): optimize
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore(fileitem): fixed width timestamp
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(fileitem): allow editing json5/jsonc
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: motd pt 1, auto backups scaffolding, editing navbar changes
* feat: fancy sidebar animations
* fix: files
* fix: files pt2
* fix: faulty name validation disallowing spaces in file names
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: fileitem props
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: upload files not refreshing files list
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(imgviewer): handle invalid/empty images
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: return of the sticky files header
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: prevent servericon from shrinking
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: wtf were we thinking with this anyway
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: further mobile optimization
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: propagate margin
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: truncation fixes
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: track navbar with sentinel
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(files): a11y
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: improve inspector styles
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: console preformance improvements, decrease blur
* feat(mobile): new server header
* fix: linting
* fix: useless z indeces
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust file filter names
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(files): true breadcrumbs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(marketing): make custom responsive
* fix(marketing): mobile file manager card
* feat: trackable navtabs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: oh no
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: smartly truncate
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(terminal): z-indexes
* fix: autofocus more inputs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: color
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust copy
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: backup modal usability improvements
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: padding
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: title
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(content): update banner mobile support
* fix: server listing icons
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: ignore clicks in server listing for labels
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(mobile): backup card
* fix(backups): make plural conditional
* fix: debounce file item selectitem
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* stuff
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: temp sidebar fix until i can be smart
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: explictly set button type in file modals
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: properly sort backups
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: add getautobackup method to pyroservers
Signed-off-by: Evan Song <theevansong@gmail.com>
* choer: update autobackup params
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update autobackup methods (REALLY GUYS)
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement autobackups
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement backup-while-running preference
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: make server labels a component
* feat: implement 'All details' modal
* fix(mobile): server manage page
* feat(files): mobile compatible
* fix(info labels): wrap
* chore(inspector): clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(backup settings): swap + and -
* fix(manage): new -> plans instead of modal
* feat: more small mobile fixes
* fix(auto backup modal): manual input validation
* fix(file browse navbar): home margin
* feat(purchase modal): mobile support
* fix(marketing): faded line alignments
* feat: add servers to mobile nav
* feat(network): dns record fixes
* feat: make all settings work on mobile
* fix(loader settings): modpack mobile
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(marketing): add 'Manage your servers' button
* fix(marketing): only check servers if logged in
* fix(network): allocation edit & delete button
* fix(backups): use UiServersTeleportOverflowMenu
* chore: linting
* chore: but here comes the sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(marketing): make buttons consistent
* lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader): prevent multiline version names in dropdown
Signed-off-by: Evan Song <theevansong@gmail.com>
* lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: copy
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: linting
* chore: rename dumbass preference key
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: rewrite power action buttons
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: robust download logic
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader mobile): modpack dropdown width
* fix: sentence case
* fix(save & 'working on it'): look good on mobile
* fix(TeleportDropdown): width
* fix(inspecting error): mobile
* fix: show action button dropdown when installing
* fix(navtabs): temp fix for mobile scrolling issue
* fix(install error): mobile compatible
* chore: just remove tracking
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: cleanup
* fix: broken svg clr in checkbox when using experimental styles
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust vanilla icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust loader props
Signed-off-by: Evan Song <theevansong@gmail.com>
* revert changes to serversidebar
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: server properties flicker
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(backups): plural
* fix: cases where the telepoverflow would clash with viewport edge
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(backups): auto-backups label
* fix(network): titlecase
* feat(fileitem): new rename icon
* fix(properties): wiki proper noun
* fix: disable motd for the time being
* chore: adjust wording for power conifmration
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: "external" to billing
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: add EULA checkbox
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* me and bro deciding which case rules to enforce
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(sftp): copy address & username, launch tooltip
* feat(files): better move
* chore: attempt to mitigate excessive stack depth type
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader): prevent versions 1.2.4 and below
* feat(dns table): placeholder improvements
* feat(pyroServer): error handling
* fix: intrinsic size on loader icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust wording
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust wording
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: types
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: "implemented" key in preference
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(connection lost): redesign
* feat(connection error): make icon orange
* fix: cleanup
* chore(connection lost): redesign pt 2
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: OOOOHHH MY GOD
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement capacity api on marketing
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update createdat backup type
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: all of backups
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update backup types
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: backups pt 2
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: comically small icons
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: align designs
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: hide ram graph if ram as bytes enabled
Signed-off-by: Evan Song <theevansong@gmail.com>
* base add content page
* Fix conflict
* feat(content): mobile-compatible header, sticky
* fix(marketing): md instead of sm for custom
* fix: compiler macro warning
Signed-off-by: Evan Song <theevansong@gmail.com>
* again
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: loader type error
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: default uptime seconds prop
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: hydration errors on server listing
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: move custom URL to general
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: indiviudally checkj capacities
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: falsey
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: missing prop
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: Derive On That Thang
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust gap
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: add default name for backups
* fix: the backup number should PROBABLY be computed lol
* fix(backups): truncate text, mobile fixes
* fix(loader): modpack mobile fix
* feat(plans): add vcpus
* fix(backup modal): blank by default, maxlength
* fix(subdomain): separate length & valid chars
* feat: mrpack installs functionality (untested), forbidden handling, backups grammar
* feat(content): make responsive on mobile
* fix: disable plan buttons separately
* fix(backup modal): update name max length
* fix(purchase): wrapping on eula, eula link
* fix: move skeleton
* fix(server mobile header): truncation
* fix(server header): proper alignment
* Finish content page fixes
* fix: who up rinthing
Signed-off-by: Evan Song <theevansong@gmail.com>
* wip
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(staging & email banner): z-index
* feat: make eula tickbox more visible
* fix: move "powered by pyro" below buttons on hero
* fix: oops sorry ellie, also updated the main screenshot
* feat: update content screenshot
* fix: content page card should hide image on lg
* feat: hide total storage for now
* fix: terminal card now uses terminal icon
* fix(marketing): make medium plan card border solid
* feat: modloader card, move pyro BACK below buttons, beta release pill
* fix: spinning logo should be behind hero
* feat: surgically remove the hero's massive forehead
* feat(marketing): mobile UI screenshot
* fix(hero): z-index goes over mobile nav
* fix: consistent borders, files breakpoints
* chore: update turbo
* chore: adjust hero sizing
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: mention region restrictions
* chore: double check if we are at capcity
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: measure twice cut once
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: bro cut twice and measured once 💀
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(marketing): login first
* fix: out of capacity text when logged out
* fix(slider): reset some values for frontend
* feat: wip hero section
Signed-off-by: Evan Song <theevansong@gmail.com>
* New navigation to support the new products (#2879)
* Nav
* oops extra file
* feat: mrpack uploading with existing modpack, fix: choose modpack duplicate
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: update features section
Signed-off-by: Evan Song <theevansong@gmail.com>
* Nav adjustments
* fix: server manager empty state clashing with loading state
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: query param hard
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: do not count uptime if crashed
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: grammar
Signed-off-by: Evan Song <theevansong@gmail.com>
* hide hero img on lg breakpoints
* Make plugins a plug
* chore: prep for buffered text selection terminal
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: marketing responsive stuff, n fixes
* fix hoverable prop
* fix: edit mod spacing
* fix: type error for display name in dropdown
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: custom plans
* fix: no more console.log
* fix: properly linked prop label
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(install hero mobile): padding
* fix: prevent x overflow on servers page
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix lint oh ym fucking god yal
Signed-off-by: Evan Song <theevansong@gmail.com>
* Migrate modpack install to search
* fix(custom plan): warning icon variable
* fix: loading probally and modal loader things
* fix(marketing): login icon colours
* fix(marketing): responsiveness
* fix(marketing): responsiveness v2
* fix: sync button for icon tm
* fix(marketing): responsiveness v3
* fix: hero image
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* Remove prod override
---------
Signed-off-by: Evan Song <theevansong@gmail.com>
Co-authored-by: Evan Song <theevansong@gmail.com>
Co-authored-by: TheWander02 <48934424+thewander02@users.noreply.github.com>
Co-authored-by: he3als <65787561+he3als@users.noreply.github.com>
Co-authored-by: Evan Song <52982404+ferothefox@users.noreply.github.com>
Co-authored-by: Lio <git@lio.cat>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: not-nullptr <needhelpwithrift@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
Co-authored-by: sticks <tanner@teamhydra.dev>
2024-11-02 23:14:00 -05:00
App redesign (#2946)
* Start of app redesign
* format
* continue progress
* Content page nearly done
* Fix recursion issues with content page
* Fix update all alignment
* Discover page progress
* Settings progress
* Removed unlocked-size hack that breaks web
* Revamp project page, refactor web project page to share code with app, fixed loading bar, misc UI/UX enhancements, update ko-fi logo, update arrow icons, fix web issues caused by floating-vue migration, fix tooltip issues, update web tooltips, clean up web hydration issues
* Ads + run prettier
* Begin auth refactor, move common messages to ui lib, add i18n extraction to all apps, begin Library refactor
* fix ads not hiding when plus log in
* rev lockfile changes/conflicts
* Fix sign in page
* Add generated
* (mostly) Data driven search
* Fix search mobile issue
* profile fixes
* Project versions page, fix typescript on UI lib and misc fixes
* Remove unused gallery component
* Fix linkfunction err
* Search filter controls at top, localization for locked filters
* Fix provided filter names
* Fix navigating from instance browse to main browse
* Friends frontend (#2995)
* Friends system frontend
* (almost) finish frontend
* finish friends, fix lint
* Fix lint
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
* Refresh macOS app icon
* Update web search UI more
* Fix link opens
* Fix frontend build
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
2024-12-11 19:54:18 -08:00
const isDiscoveringSubpage = computed (
2025-08-14 21:48:38 +01:00
( ) => route . name && route . name . startsWith ( 'type-id' ) && ! route . query . sid ,
)
Pyro Integration (#2503)
* fix
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor(fileitem): optimize
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore(fileitem): fixed width timestamp
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(fileitem): allow editing json5/jsonc
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: motd pt 1, auto backups scaffolding, editing navbar changes
* feat: fancy sidebar animations
* fix: files
* fix: files pt2
* fix: faulty name validation disallowing spaces in file names
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: fileitem props
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: upload files not refreshing files list
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(imgviewer): handle invalid/empty images
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: return of the sticky files header
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: prevent servericon from shrinking
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: wtf were we thinking with this anyway
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: further mobile optimization
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: propagate margin
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: truncation fixes
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: track navbar with sentinel
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(files): a11y
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: improve inspector styles
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: console preformance improvements, decrease blur
* feat(mobile): new server header
* fix: linting
* fix: useless z indeces
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust file filter names
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(files): true breadcrumbs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(marketing): make custom responsive
* fix(marketing): mobile file manager card
* feat: trackable navtabs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: oh no
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: smartly truncate
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(terminal): z-indexes
* fix: autofocus more inputs
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: color
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust copy
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: backup modal usability improvements
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: padding
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: title
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(content): update banner mobile support
* fix: server listing icons
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: ignore clicks in server listing for labels
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(mobile): backup card
* fix(backups): make plural conditional
* fix: debounce file item selectitem
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* stuff
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: temp sidebar fix until i can be smart
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: explictly set button type in file modals
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: properly sort backups
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: add getautobackup method to pyroservers
Signed-off-by: Evan Song <theevansong@gmail.com>
* choer: update autobackup params
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update autobackup methods (REALLY GUYS)
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement autobackups
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement backup-while-running preference
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: make server labels a component
* feat: implement 'All details' modal
* fix(mobile): server manage page
* feat(files): mobile compatible
* fix(info labels): wrap
* chore(inspector): clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(backup settings): swap + and -
* fix(manage): new -> plans instead of modal
* feat: more small mobile fixes
* fix(auto backup modal): manual input validation
* fix(file browse navbar): home margin
* feat(purchase modal): mobile support
* fix(marketing): faded line alignments
* feat: add servers to mobile nav
* feat(network): dns record fixes
* feat: make all settings work on mobile
* fix(loader settings): modpack mobile
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(marketing): add 'Manage your servers' button
* fix(marketing): only check servers if logged in
* fix(network): allocation edit & delete button
* fix(backups): use UiServersTeleportOverflowMenu
* chore: linting
* chore: but here comes the sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(marketing): make buttons consistent
* lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader): prevent multiline version names in dropdown
Signed-off-by: Evan Song <theevansong@gmail.com>
* lint
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: copy
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: linting
* chore: rename dumbass preference key
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: rewrite power action buttons
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: robust download logic
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader mobile): modpack dropdown width
* fix: sentence case
* fix(save & 'working on it'): look good on mobile
* fix(TeleportDropdown): width
* fix(inspecting error): mobile
* fix: show action button dropdown when installing
* fix(navtabs): temp fix for mobile scrolling issue
* fix(install error): mobile compatible
* chore: just remove tracking
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: cleanup
* fix: broken svg clr in checkbox when using experimental styles
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust vanilla icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust loader props
Signed-off-by: Evan Song <theevansong@gmail.com>
* revert changes to serversidebar
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: server properties flicker
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(backups): plural
* fix: cases where the telepoverflow would clash with viewport edge
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(backups): auto-backups label
* fix(network): titlecase
* feat(fileitem): new rename icon
* fix(properties): wiki proper noun
* fix: disable motd for the time being
* chore: adjust wording for power conifmration
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: "external" to billing
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: add EULA checkbox
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* me and bro deciding which case rules to enforce
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(sftp): copy address & username, launch tooltip
* feat(files): better move
* chore: attempt to mitigate excessive stack depth type
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(loader): prevent versions 1.2.4 and below
* feat(dns table): placeholder improvements
* feat(pyroServer): error handling
* fix: intrinsic size on loader icon
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust wording
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: sentence case
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust wording
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: types
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: "implemented" key in preference
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat(connection lost): redesign
* feat(connection error): make icon orange
* fix: cleanup
* chore(connection lost): redesign pt 2
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: OOOOHHH MY GOD
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: implement capacity api on marketing
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update createdat backup type
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: all of backups
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: update backup types
Signed-off-by: Evan Song <theevansong@gmail.com>
* refactor: backups pt 2
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: comically small icons
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: align designs
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: hide ram graph if ram as bytes enabled
Signed-off-by: Evan Song <theevansong@gmail.com>
* base add content page
* Fix conflict
* feat(content): mobile-compatible header, sticky
* fix(marketing): md instead of sm for custom
* fix: compiler macro warning
Signed-off-by: Evan Song <theevansong@gmail.com>
* again
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: loader type error
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: default uptime seconds prop
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: hydration errors on server listing
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: move custom URL to general
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: indiviudally checkj capacities
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: falsey
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: missing prop
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: Derive On That Thang
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: adjust gap
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: add default name for backups
* fix: the backup number should PROBABLY be computed lol
* fix(backups): truncate text, mobile fixes
* fix(loader): modpack mobile fix
* feat(plans): add vcpus
* fix(backup modal): blank by default, maxlength
* fix(subdomain): separate length & valid chars
* feat: mrpack installs functionality (untested), forbidden handling, backups grammar
* feat(content): make responsive on mobile
* fix: disable plan buttons separately
* fix(backup modal): update name max length
* fix(purchase): wrapping on eula, eula link
* fix: move skeleton
* fix(server mobile header): truncation
* fix(server header): proper alignment
* Finish content page fixes
* fix: who up rinthing
Signed-off-by: Evan Song <theevansong@gmail.com>
* wip
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(staging & email banner): z-index
* feat: make eula tickbox more visible
* fix: move "powered by pyro" below buttons on hero
* fix: oops sorry ellie, also updated the main screenshot
* feat: update content screenshot
* fix: content page card should hide image on lg
* feat: hide total storage for now
* fix: terminal card now uses terminal icon
* fix(marketing): make medium plan card border solid
* feat: modloader card, move pyro BACK below buttons, beta release pill
* fix: spinning logo should be behind hero
* feat: surgically remove the hero's massive forehead
* feat(marketing): mobile UI screenshot
* fix(hero): z-index goes over mobile nav
* fix: consistent borders, files breakpoints
* chore: update turbo
* chore: adjust hero sizing
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: mention region restrictions
* chore: double check if we are at capcity
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: measure twice cut once
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: bro cut twice and measured once 💀
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(marketing): login first
* fix: out of capacity text when logged out
* fix(slider): reset some values for frontend
* feat: wip hero section
Signed-off-by: Evan Song <theevansong@gmail.com>
* New navigation to support the new products (#2879)
* Nav
* oops extra file
* feat: mrpack uploading with existing modpack, fix: choose modpack duplicate
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: update features section
Signed-off-by: Evan Song <theevansong@gmail.com>
* Nav adjustments
* fix: server manager empty state clashing with loading state
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: query param hard
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: do not count uptime if crashed
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: grammar
Signed-off-by: Evan Song <theevansong@gmail.com>
* hide hero img on lg breakpoints
* Make plugins a plug
* chore: prep for buffered text selection terminal
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix: marketing responsive stuff, n fixes
* fix hoverable prop
* fix: edit mod spacing
* fix: type error for display name in dropdown
Signed-off-by: Evan Song <theevansong@gmail.com>
* feat: custom plans
* fix: no more console.log
* fix: properly linked prop label
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix(install hero mobile): padding
* fix: prevent x overflow on servers page
Signed-off-by: Evan Song <theevansong@gmail.com>
* fix lint oh ym fucking god yal
Signed-off-by: Evan Song <theevansong@gmail.com>
* Migrate modpack install to search
* fix(custom plan): warning icon variable
* fix: loading probally and modal loader things
* fix(marketing): login icon colours
* fix(marketing): responsiveness
* fix(marketing): responsiveness v2
* fix: sync button for icon tm
* fix(marketing): responsiveness v3
* fix: hero image
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: clean
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* chore: switch to cdn links
Signed-off-by: Evan Song <theevansong@gmail.com>
* Remove prod override
---------
Signed-off-by: Evan Song <theevansong@gmail.com>
Co-authored-by: Evan Song <theevansong@gmail.com>
Co-authored-by: TheWander02 <48934424+thewander02@users.noreply.github.com>
Co-authored-by: he3als <65787561+he3als@users.noreply.github.com>
Co-authored-by: Evan Song <52982404+ferothefox@users.noreply.github.com>
Co-authored-by: Lio <git@lio.cat>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: not-nullptr <needhelpwithrift@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
Co-authored-by: sticks <tanner@teamhydra.dev>
2024-11-02 23:14:00 -05:00
2025-10-01 19:00:01 -07:00
const isRussia = computed ( ( ) => country . value === 'ru' )
2025-08-14 21:48:38 +01:00
const rCount = ref ( 0 )
2025-03-03 22:22:10 -08:00
2025-08-14 21:48:38 +01:00
const randomProjects = ref ( [ ] )
const disableRandomProjects = ref ( false )
2025-03-03 22:22:10 -08:00
const disableRandomProjectsForRoute = computed (
2025-08-14 21:48:38 +01:00
( ) =>
route . name . startsWith ( 'servers' ) ||
route . name . includes ( 'settings' ) ||
route . name . includes ( 'admin' ) ,
)
2025-03-03 22:22:10 -08:00
async function onKeyDown ( event ) {
2025-08-14 21:48:38 +01:00
if ( disableRandomProjects . value || disableRandomProjectsForRoute . value ) {
return
}
if ( event . key === 'r' ) {
rCount . value ++
if ( randomProjects . value . length < 3 ) {
randomProjects . value = await useBaseFetch ( 'projects_random?count=50' ) . catch ( ( err ) => {
console . error ( err )
return [ ]
} )
}
}
if ( rCount . value >= 40 ) {
rCount . value = 0
const randomProject = randomProjects . value [ 0 ]
await router . push ( ` /project/ ${ randomProject . slug } ` )
randomProjects . value . splice ( 0 , 1 )
}
2025-03-03 22:22:10 -08:00
}
function onKeyUp ( event ) {
2025-08-14 21:48:38 +01:00
if ( event . key === 'r' ) {
rCount . value = 0
}
2025-03-03 22:22:10 -08:00
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
onMounted ( ( ) => {
2025-08-14 21:48:38 +01:00
if ( window && import . meta . client ) {
window . history . scrollRestoration = 'auto'
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2025-08-14 21:48:38 +01:00
runAnalytics ( )
2025-03-03 22:22:10 -08:00
2025-08-14 21:48:38 +01:00
window . addEventListener ( 'keydown' , onKeyDown )
window . addEventListener ( 'keyup' , onKeyUp )
} )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
watch (
2025-08-14 21:48:38 +01:00
( ) => route . path ,
( ) => {
isMobileMenuOpen . value = false
isBrowseMenuOpen . value = false
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2025-08-14 21:48:38 +01:00
if ( import . meta . client ) {
document . body . style . overflowY = 'scroll'
document . body . setAttribute ( 'tabindex' , '-1' )
document . body . removeAttribute ( 'tabindex' )
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2025-08-14 21:48:38 +01:00
runAnalytics ( )
} ,
)
2023-07-15 20:39:33 -07:00
function developerModeIncrement ( ) {
2025-08-14 21:48:38 +01:00
if ( developerModeCounter . value >= 5 ) {
flags . value . developerMode = ! flags . value . developerMode
developerModeCounter . value = 0
saveFeatureFlags ( )
if ( flags . value . developerMode ) {
addNotification ( {
title : 'Developer mode activated' ,
text : 'Developer mode has been enabled' ,
type : 'success' ,
} )
} else {
addNotification ( {
title : 'Developer mode deactivated' ,
text : 'Developer mode has been disabled' ,
type : 'success' ,
} )
}
} else {
developerModeCounter . value ++
}
2023-07-15 20:39:33 -07:00
}
2023-07-20 11:19:42 -07:00
async function logoutUser ( ) {
2025-08-14 21:48:38 +01:00
await logout ( )
2023-07-20 11:19:42 -07:00
}
2024-01-11 16:12:25 -08:00
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
function runAnalytics ( ) {
2025-08-14 21:48:38 +01:00
const config = useRuntimeConfig ( )
const replacedUrl = config . public . apiBaseUrl . replace ( 'v2/' , '' )
try {
setTimeout ( ( ) => {
$fetch ( ` ${ replacedUrl } analytics/view ` , {
method : 'POST' ,
body : {
url : window . location . href ,
} ,
headers : {
Authorization : auth . value . token ,
} ,
} )
. then ( ( ) => { } )
. catch ( ( ) => { } )
} )
} catch ( e ) {
console . error ( ` Sending analytics failed (CORS error? If so, ignore) ` , e )
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
}
function toggleMobileMenu ( ) {
2025-08-14 21:48:38 +01:00
isMobileMenuOpen . value = ! isMobileMenuOpen . value
if ( isMobileMenuOpen . value ) {
isBrowseMenuOpen . value = false
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
}
function toggleBrowseMenu ( ) {
2025-08-14 21:48:38 +01:00
isBrowseMenuOpen . value = ! isBrowseMenuOpen . value
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2025-08-14 21:48:38 +01:00
if ( isBrowseMenuOpen . value ) {
isMobileMenuOpen . value = false
}
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
}
2024-07-31 21:42:55 +02:00
2025-08-14 21:48:38 +01:00
const { cycle : changeTheme } = useTheme ( )
Add translations for the default page layout (#1616)
* Convert default.vue to composition API
* Add translations to default page layout
* Generate index.json
* Fix sign up page
* Generate index.json
* Fix atUserLabel
* Fix composition API port
* Follow-up fixes for #1616 (#1618)
* Re-organize default layout messages
- Group some of the messages by their appearance (like banners)
Grouping makes avoids having to think too much about the property
names, keeps declarations clean, and also can be minified better,
since variable names, unlike property names, can be easily mangled.
- Remove needless type specification in property name[^1]
It's already clear from where the message is formatted what it does,
and if you need clarification, you can Ctrl+hover and see the type in
the key.
- Change some keys to conform to conventions
We generally follow the pattern location > kind?. Things like 'label'
are unnecessary, as everything is assumed to be label by default; the
same applies to things like 'button', which are also often unnecessary
as they're part of the location compound.
- Remove message for handle, which should not be translatable
It's very unlikely user handle format changes between any of the
locales.
[^1]: Common messages are pending restructuring that would fix this
* Fix navRoutes not being computed in default layout
* Fix untranslated Get Modrinth App buttons in default layout
* Make legal disclaimer in the default layout translatable
It wouldn't make much sense to leave it untranslated since it is meant
for the end users too. It is also so small that it's unlikely to be
mistranslated.
* Extract missed legal disclaimer message from default layout
* Make SEO strings in default layout translatable
---------
Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
2024-01-29 18:55:54 -08:00
2024-01-11 16:12:25 -08:00
function hideStagingBanner ( ) {
2025-08-14 21:48:38 +01:00
cosmetics . value . hideStagingBanner = true
2024-01-11 16:12:25 -08:00
}
2025-02-19 22:01:29 -08:00
2025-10-01 19:00:01 -07:00
function hideRussiaCensorshipBanner ( ) {
flags . value . hideRussiaCensorshipBanner = true
saveFeatureFlags ( )
}
2025-02-19 22:01:29 -08:00
const socialLinks = [
2025-08-14 21:48:38 +01:00
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.social.discord' , defaultMessage : 'Discord' } ) ,
) ,
href : 'https://discord.modrinth.com' ,
icon : DiscordIcon ,
} ,
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.social.bluesky' , defaultMessage : 'Bluesky' } ) ,
) ,
href : 'https://bsky.app/profile/modrinth.com' ,
icon : BlueskyIcon ,
} ,
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.social.mastodon' , defaultMessage : 'Mastodon' } ) ,
) ,
href : 'https://floss.social/@modrinth' ,
icon : MastodonIcon ,
rel : 'me' ,
} ,
{
label : formatMessage ( defineMessage ( { id : 'layout.footer.social.x' , defaultMessage : 'X' } ) ) ,
href : 'https://x.com/modrinth' ,
icon : TwitterIcon ,
} ,
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.social.github' , defaultMessage : 'GitHub' } ) ,
) ,
href : 'https://github.com/modrinth' ,
icon : GithubIcon ,
} ,
]
2025-02-19 22:01:29 -08:00
const footerLinks = [
2025-08-14 21:48:38 +01:00
{
label : formatMessage ( defineMessage ( { id : 'layout.footer.about' , defaultMessage : 'About' } ) ) ,
links : [
{
href : '/news' ,
label : formatMessage (
defineMessage ( { id : 'layout.footer.about.news' , defaultMessage : 'News' } ) ,
) ,
} ,
{
href : '/news/changelog' ,
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.about.changelog' , defaultMessage : 'Changelog' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : 'https://status.modrinth.com' ,
label : formatMessage (
defineMessage ( { id : 'layout.footer.about.status' , defaultMessage : 'Status' } ) ,
) ,
} ,
{
href : 'https://careers.modrinth.com' ,
label : formatMessage (
defineMessage ( { id : 'layout.footer.about.careers' , defaultMessage : 'Careers' } ) ,
) ,
} ,
{
href : '/legal/cmp-info' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.about.rewards-program' ,
defaultMessage : 'Rewards Program' ,
} ) ,
) ,
} ,
] ,
} ,
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.products' , defaultMessage : 'Products' } ) ,
) ,
links : [
{
href : '/plus' ,
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.products.plus' , defaultMessage : 'Modrinth+' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : '/app' ,
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.products.app' , defaultMessage : 'Modrinth App' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : '/servers' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.products.servers' ,
defaultMessage : 'Modrinth Servers' ,
} ) ,
) ,
} ,
] ,
} ,
{
label : formatMessage (
defineMessage ( { id : 'layout.footer.resources' , defaultMessage : 'Resources' } ) ,
) ,
links : [
{
href : 'https://support.modrinth.com' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.resources.help-center' ,
defaultMessage : 'Help Center' ,
} ) ,
) ,
} ,
{
2025-08-25 22:50:01 +01:00
href : 'https://translate.modrinth.com' ,
2025-08-14 21:48:38 +01:00
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.resources.translate' , defaultMessage : 'Translate' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : 'https://github.com/modrinth/code/issues' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.resources.report-issues' ,
defaultMessage : 'Report issues' ,
} ) ,
) ,
} ,
{
href : 'https://docs.modrinth.com/api/' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.resources.api-docs' ,
defaultMessage : 'API documentation' ,
} ) ,
) ,
} ,
] ,
} ,
{
label : formatMessage ( defineMessage ( { id : 'layout.footer.legal' , defaultMessage : 'Legal' } ) ) ,
links : [
{
href : '/legal/rules' ,
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.legal.rules' , defaultMessage : 'Content Rules' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : '/legal/terms' ,
label : formatMessage (
2025-08-17 12:15:49 +01:00
defineMessage ( { id : 'layout.footer.legal.terms-of-use' , defaultMessage : 'Terms of Use' } ) ,
2025-08-14 21:48:38 +01:00
) ,
} ,
{
href : '/legal/privacy' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.legal.privacy-policy' ,
defaultMessage : 'Privacy Policy' ,
} ) ,
) ,
} ,
{
href : '/legal/security' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.legal.security-notice' ,
defaultMessage : 'Security Notice' ,
} ) ,
) ,
} ,
{
href : '/legal/copyright' ,
label : formatMessage (
defineMessage ( {
id : 'layout.footer.legal.copyright-policy' ,
defaultMessage : 'Copyright Policy and DMCA' ,
} ) ,
) ,
} ,
] ,
} ,
]
2023-03-09 10:05:32 -07:00
< / script >
2020-09-13 20:11:34 -07:00
2020-06-29 11:56:46 +03:00
< style lang = "scss" >
2025-08-14 21:48:38 +01:00
@ import '~/assets/styles/global.scss' ;
2024-07-04 21:46:29 -07:00
// @import '@modrinth/assets';
2022-05-18 03:31:58 +02:00
2020-06-29 11:56:46 +03:00
. layout {
2025-08-14 21:48:38 +01:00
min - height : 100 vh ;
display : block ;
2020-09-18 15:05:13 -05:00
2025-08-14 21:48:38 +01:00
@ media screen and ( min - width : 1024 px ) {
min - height : calc ( 100 vh - var ( -- spacing - card - bg ) ) ;
}
Add initial support for the v2 of the API (Still WIP) (#250)
* Functionally implement modpacks
* Add LogoAnimated to logo license
* Fix eslint errors
* Add `z-index: 20` to user dropdown (#287)
* Fix pages not working, add changelog page, redesign versions page
* Update theme colors, add OLED theme, update some project creation text. (#292)
* Update theme colors, add OLED theme, update some project creation text.
* Make summary normal text color
* Update favicons, update logos to use dynamic colors, updated filters panel a bit
* Update wording from #250
* Version page rework
* Manually apply some commits from master, other minor v2 fixes (#296)
* Homepage styling improvements (#285)
* Add border radius to video + example code colors
* Change color + allow overflow scroll
* Minor v2 fixes
- Makes multiple loaders display correctly (used to be `Fabric,Forge` is now `Fabric, Forge`
- Fix oopses in #292
- Allow .jar and .zip in file prompt
- Apply 30cbd3a6c372940d1e86cc8134d0dfc7e8e5ee9c to pages/create/project.vue
- Display `fabric, forge` instead of broken icons on pages/create/project.vue
* Markdown styling fixes (#268)
* Add table color variables (+ prettier fixes)
* Add details and table styling to .markdown-body
* Add indexing meta value depending on the status of the mod. (#261)
* General UI Improvement (again) (#255)
* Add and fix some stuff
* Add warning when leaving to `mod/create`
* Fix mods/create not working
* Fix a bug & add improvements to a couple moderation aspects (#278)
This PR fixes reports on the moderation dashboard going to `/dashboard/mod/_id` instead of to `/mod/_id`.
It also allows the ability for moderators to unlist mods in the queue from the frontend instead of having to do it via the backend.

Unlisted mods should have the ability to resubmit for approval, so I've also changed "Submit for Review" to "Submit for approval", allowing unlisted mods to do that as well.

* Add project guidelines to Terms page (#275)
* Add project guidelines to Terms page
This adds the project guidelines as outlined [here](https://discord.com/channels/734077874708938864/734077874708938867/806556531491471368).
NOTE: I've made a few tweaks in wording to accommodate this format, so this is not an exact copy.
* Move rules to its own page
* Allow users to login from search page when it is rendered serverside (#272)
* Change `this.$route.fullPath` → `this.$route.path`
* Closes modrinth/knossos#256
* Wrap mod icon and title in link (#273)
* Wrap mod icon and title in link
* Fixes #218
* Editor's note
Skipped #249 (search was rewritten), #266 (couldn't figure out how to apply it), #270 (didn't seem to apply properly), #252 (manually merged in with #292), #262 (superceded by #270), #282, #271, #277, #283, and #281 (those five didn't get wiped)
Co-authored-by: venashial <venashial.levo@aleeas.com>
Co-authored-by: Redblueflame <contact@redblueflame.com>
Co-authored-by: Johan Novak <wickedtree@wickedtree.codes>
* SSR descriptions, version edit page
* Working version editing + dependency management (besides files)
* Version create page, file functionality
* Fix some issues with the version page
* More versions page fixes
* Project gallery
* Box shadows, user profile page, WIP header
* Finish user dashboard
* Finish search and fix minor issues
* Moderator page + messages, notifications page
* Fix dropdown menu, fix XSS, fix team members page
* Change doc url on main page (#309)
* Re-Fix docs url (#313)
* Clean up. Part 1: Fix immediate problems (#316)
* Clean up tabs and cards CSS a little
* Fix project page; Remove bad styles from search
* Yeet and flatten lots of styles; fix font sizes
* Restyle search; fix moderation
* Fix profile page
* Remove injected SCSS entirely
* Fix a mobile layout overflowing
* Apiv2-support fixes (#320)
* Fix member user_id -> user.id
* Fix incorrect report redirect
* Change theme switcher from button to multiselect
* Fix remaining items
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
* Fix bugs
* Full mobile support, update create project page, fix various bugs
* New Dark Mode brand colors (#325)
* Use "color-brand-hover" for auth-prompt when hover over
* New dark mode brand colors
* Fix new version featured bug
* Remove old home page, other fixes
* Fix error when merging
* Fix prettier error :(
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: venashial <venashial.levo@aleeas.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Emma <emmaffle@modrinth.com>
Co-authored-by: Johan Novak <wickedtree@wickedtree.codes>
Co-authored-by: Jai A <jaiagr@pm.me>
Co-authored-by: Mysterious_Dev <40738104+Mysterious-Dev@users.noreply.github.com>
Co-authored-by: Mikhail Oleynikov <contact@falseresync.ru>
Co-authored-by: Christian Popov <30723811+Xrey274@users.noreply.github.com>
2022-01-09 23:19:27 +01:00
2025-08-14 21:48:38 +01:00
main {
grid - area : main ;
}
2020-06-29 11:56:46 +03:00
}
2020-09-08 22:09:46 -07:00
2020-11-30 13:55:01 -08:00
@ media ( min - width : 1024 px ) {
2025-08-14 21:48:38 +01:00
. layout {
main {
. alpha - alert {
margin : 1 rem ;
. wrapper {
padding : 1 rem 2 rem 1 rem 1 rem ;
}
}
}
}
2020-09-08 22:09:46 -07:00
}
2023-07-20 11:19:42 -07:00
2023-09-25 22:28:48 -05:00
@ media ( max - width : 1200 px ) {
2025-08-14 21:48:38 +01:00
. app - btn {
display : none ;
}
2023-09-25 22:28:48 -05:00
}
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
. mobile - navigation {
2025-08-14 21:48:38 +01:00
display : none ;
. nav - menu {
width : 100 % ;
position : fixed ;
bottom : calc ( var ( -- size - mobile - navbar - height ) - var ( -- size - rounded - card ) ) ;
padding - bottom : var ( -- size - rounded - card ) ;
left : 0 ;
background - color : var ( -- color - raised - bg ) ;
2025-11-12 04:00:46 +00:00
z - index : 11 ; // 20 = modals, 10 = svg icons
2025-08-14 21:48:38 +01:00
transform : translateY ( 100 % ) ;
transition : transform 0.4 s cubic - bezier ( 0.54 , 0.84 , 0.42 , 1 ) ;
border - radius : var ( -- size - rounded - card ) var ( -- size - rounded - card ) 0 0 ;
box - shadow : 0 0 20 px 2 px rgba ( 0 , 0 , 0 , 0 ) ;
. links ,
. account - container {
display : grid ;
grid - template - columns : repeat ( 1 , 1 fr ) ;
grid - gap : 1 rem ;
justify - content : center ;
padding : 1 rem ;
. iconified - button {
width : 100 % ;
max - width : 500 px ;
padding : 0.75 rem ;
justify - content : center ;
font - weight : 600 ;
font - size : 1 rem ;
margin : 0 auto ;
}
}
. cascade - links {
@ media screen and ( min - width : 354 px ) {
grid - template - columns : repeat ( 2 , 1 fr ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
@ media screen and ( min - width : 674 px ) {
grid - template - columns : repeat ( 3 , 1 fr ) ;
}
}
& - browse {
& . expanded {
transform : translateY ( 0 ) ;
box - shadow : 0 0 20 px 2 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
}
& - mobile {
. account - container {
padding - bottom : 0 ;
. account - button {
padding : var ( -- spacing - card - md ) ;
display : flex ;
align - items : center ;
justify - content : center ;
gap : 0.5 rem ;
. user - icon {
width : 2.25 rem ;
height : 2.25 rem ;
}
. account - text {
flex - grow : 0 ;
}
}
}
& . expanded {
transform : translateY ( 0 ) ;
box - shadow : 0 0 20 px 2 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
}
}
. mobile - navbar {
display : flex ;
height : calc ( var ( -- size - mobile - navbar - height ) + env ( safe - area - inset - bottom ) ) ;
border - radius : var ( -- size - rounded - card ) var ( -- size - rounded - card ) 0 0 ;
padding - bottom : env ( safe - area - inset - bottom ) ;
position : fixed ;
left : 0 ;
bottom : 0 ;
background - color : var ( -- color - raised - bg ) ;
box - shadow : 0 0 20 px 2 px rgba ( 0 , 0 , 0 , 0.3 ) ;
2025-11-12 04:00:46 +00:00
z - index : 11 ; // 20 = modals, 10 = svg icons
2025-08-14 21:48:38 +01:00
width : 100 % ;
align - items : center ;
justify - content : space - between ;
transition : border - radius 0.3 s ease - out ;
border - top : 2 px solid rgba ( 0 , 0 , 0 , 0 ) ;
box - sizing : border - box ;
& . expanded {
box - shadow : none ;
border - radius : 0 ;
}
. tab {
position : relative ;
background : none ;
display : flex ;
flex - basis : 0 ;
justify - content : center ;
align - items : center ;
flex - direction : row ;
gap : 0.25 rem ;
font - weight : bold ;
padding : 0 ;
transition : color ease - in - out 0.15 s ;
color : var ( -- color - text - inactive ) ;
text - align : center ;
& . browse {
svg {
transform : rotate ( 180 deg ) ;
transition : transform ease - in - out 0.3 s ;
& . closed {
transform : rotate ( 0 deg ) ;
}
}
}
& . bubble {
& : : after {
background - color : var ( -- color - brand ) ;
border - radius : var ( -- size - rounded - max ) ;
content : '' ;
height : 0.5 rem ;
position : absolute ;
left : 1.5 rem ;
top : 0 ;
width : 0.5 rem ;
}
}
svg {
height : 1.75 rem ;
width : 1.75 rem ;
& . smaller {
width : 1.25 rem ;
height : 1.25 rem ;
}
}
. user - icon {
width : 2 rem ;
height : 2 rem ;
transition : border ease - in - out 0.15 s ;
border : 0 solid var ( -- color - brand ) ;
box - sizing : border - box ;
& . expanded {
border : 2 px solid var ( -- color - brand ) ;
}
}
& : hover ,
& : focus {
color : var ( -- color - text ) ;
}
& : first - child {
margin - left : 2 rem ;
}
& : last - child {
margin - right : 2 rem ;
}
& . router - link - exact - active : not ( & . no - active ) {
svg {
color : var ( -- color - brand ) ;
}
color : var ( -- color - brand ) ;
}
}
}
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
}
@ media ( any - hover : none ) and ( max - width : 640 px ) {
2025-08-14 21:48:38 +01:00
. desktop - only {
display : none ;
}
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
}
@ media ( any - hover : none ) and ( max - width : 640 px ) {
2025-08-14 21:48:38 +01:00
. mobile - navigation {
display : flex ;
}
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
}
2025-02-19 22:01:29 -08:00
. footer - brand - background {
2025-08-14 21:48:38 +01:00
background : var ( -- brand - gradient - strong - bg ) ;
border - color : var ( -- brand - gradient - border ) ;
2025-02-19 22:01:29 -08:00
}
2025-03-03 22:22:10 -08:00
. over - the - top - random - animation {
2025-08-14 21:48:38 +01:00
position : fixed ;
z - index : 100 ;
inset : 0 ;
display : flex ;
justify - content : center ;
align - items : center ;
pointer - events : none ;
scale : 0.5 ;
transition : all 0.5 s ease - out ;
opacity : 0 ;
animation :
tilt - shaking calc ( 0.2 s / ( max ( ( var ( -- _r - count ) - 20 ) , 1 ) / 20 ) ) linear infinite ,
translate - x - shaking calc ( 0.3 s / ( max ( ( var ( -- _r - count ) - 20 ) , 1 ) / 20 ) ) linear infinite ,
translate - y - shaking calc ( 0.25 s / ( max ( ( var ( -- _r - count ) - 20 ) , 1 ) / 20 ) ) linear infinite ;
& . threshold {
opacity : 1 ;
}
& . rings - expand {
scale : 0.8 ;
opacity : 0 ;
. animation - ring - 1 {
width : 25 rem ;
height : 25 rem ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
. animation - ring - 2 {
width : 50 rem ;
height : 50 rem ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
. animation - ring - 3 {
width : 100 rem ;
height : 100 rem ;
}
}
> div {
position : relative ;
display : flex ;
justify - content : center ;
align - items : center ;
width : fit - content ;
height : fit - content ;
> * {
position : absolute ;
scale : calc ( 1 + max ( ( var ( -- _r - count ) - 20 ) , 0 ) * 0.1 ) ;
transition : all 0.2 s ease - out ;
width : 20 rem ;
height : 20 rem ;
}
}
2025-03-03 22:22:10 -08:00
}
@ keyframes tilt - shaking {
2025-08-14 21:48:38 +01:00
0 % {
rotate : 0 deg ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
25 % {
rotate : calc ( 1 deg * ( var ( -- _r - count ) - 20 ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
50 % {
rotate : 0 deg ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
75 % {
rotate : calc ( - 1 deg * ( var ( -- _r - count ) - 20 ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
100 % {
rotate : 0 deg ;
}
2025-03-03 22:22:10 -08:00
}
@ keyframes translate - x - shaking {
2025-08-14 21:48:38 +01:00
0 % {
translate : 0 ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
25 % {
translate : calc ( 2 px * ( var ( -- _r - count ) - 20 ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
50 % {
translate : 0 ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
75 % {
translate : calc ( - 2 px * ( var ( -- _r - count ) - 20 ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
100 % {
translate : 0 ;
}
2025-03-03 22:22:10 -08:00
}
@ keyframes translate - y - shaking {
2025-08-14 21:48:38 +01:00
0 % {
transform : translateY ( 0 ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
25 % {
transform : translateY ( calc ( 2 px * ( var ( -- _r - count ) - 20 ) ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
50 % {
transform : translateY ( 0 ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
75 % {
transform : translateY ( calc ( - 2 px * ( var ( -- _r - count ) - 20 ) ) ) ;
}
2025-10-19 22:03:21 +01:00
2025-08-14 21:48:38 +01:00
100 % {
transform : translateY ( 0 ) ;
}
2025-03-03 22:22:10 -08:00
}
2020-06-29 11:56:46 +03:00
< / style >
2023-03-09 10:05:32 -07:00
< style src = "vue-multiselect/dist/vue-multiselect.css" > < / style >