Updated ad placeholder graphics, update Modrinth App sidebar to mockup designs (#4584)

* Update ad placeholders to new green graphic

* Remove rounded corners from app ad frame

* Improve web ad placeholder styling

* Revamp app sidebar to match mockups more closely, greatly improve friends UX, fix up context menus and typify shit

* only show overflow on hover

* lint

* intl:extract

* clean up the inline code in FriendsSection
This commit is contained in:
Prospector
2025-10-19 16:26:17 -07:00
committed by GitHub
parent e58456eed4
commit 6a70acef25
19 changed files with 745 additions and 340 deletions

View File

@@ -188,6 +188,7 @@ import _UnplugIcon from './icons/unplug.svg?component'
import _UpdatedIcon from './icons/updated.svg?component'
import _UploadIcon from './icons/upload.svg?component'
import _UserIcon from './icons/user.svg?component'
import _UserCogIcon from './icons/user-cog.svg?component'
import _UserPlusIcon from './icons/user-plus.svg?component'
import _UserXIcon from './icons/user-x.svg?component'
import _UsersIcon from './icons/users.svg?component'
@@ -387,6 +388,7 @@ export const UnlinkIcon = _UnlinkIcon
export const UnplugIcon = _UnplugIcon
export const UpdatedIcon = _UpdatedIcon
export const UploadIcon = _UploadIcon
export const UserCogIcon = _UserCogIcon
export const UserPlusIcon = _UserPlusIcon
export const UserXIcon = _UserXIcon
export const UserIcon = _UserIcon

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user-cog-icon lucide-user-cog"><path d="M10 15H6a4 4 0 0 0-4 4v2"/><path d="m14.305 16.53.923-.382"/><path d="m15.228 13.852-.923-.383"/><path d="m16.852 12.228-.383-.923"/><path d="m16.852 17.772-.383.924"/><path d="m19.148 12.228.383-.923"/><path d="m19.53 18.696-.382-.924"/><path d="m20.772 13.852.924-.383"/><path d="m20.772 16.148.924.383"/><circle cx="18" cy="15" r="3"/><circle cx="9" cy="7" r="4"/></svg>

After

Width:  |  Height:  |  Size: 615 B

View File

@@ -1,36 +1,36 @@
// AUTO-GENERATED FILE - DO NOT EDIT
import { article as windows_borderless_malware_disclosure } from "./windows_borderless_malware_disclosure";
import { article as whats_modrinth } from "./whats_modrinth";
import { article as two_years_of_modrinth } from "./two_years_of_modrinth";
import { article as two_years_of_modrinth_history } from "./two_years_of_modrinth_history";
import { article as a_new_chapter_for_modrinth_servers } from "./a_new_chapter_for_modrinth_servers";
import { article as accelerating_development } from "./accelerating_development";
import { article as becoming_sustainable } from "./becoming_sustainable";
import { article as capital_return } from "./capital_return";
import { article as carbon_ads } from "./carbon_ads";
import { article as creator_monetization } from "./creator_monetization";
import { article as creator_update } from "./creator_update";
import { article as creator_updates_july_2025 } from "./creator_updates_july_2025";
import { article as design_refresh } from "./design_refresh";
import { article as download_adjustment } from "./download_adjustment";
import { article as free_server_medal } from "./free_server_medal";
import { article as knossos_v2_1_0 } from "./knossos_v2_1_0";
import { article as licensing_guide } from "./licensing_guide";
import { article as modpack_changes } from "./modpack_changes";
import { article as modpacks_alpha } from "./modpacks_alpha";
import { article as modrinth_app_beta } from "./modrinth_app_beta";
import { article as modrinth_beta } from "./modrinth_beta";
import { article as modrinth_servers_asia } from "./modrinth_servers_asia";
import { article as modrinth_servers_beta } from "./modrinth_servers_beta";
import { article as new_environments } from "./new_environments";
import { article as new_site_beta } from "./new_site_beta";
import { article as plugins_resource_packs } from "./plugins_resource_packs";
import { article as pride_campaign_2025 } from "./pride_campaign_2025";
import { article as redesign } from "./redesign";
import { article as russian_censorship } from "./russian_censorship";
import { article as skins_now_in_modrinth_app } from "./skins_now_in_modrinth_app";
import { article as standing_by_our_values } from "./standing_by_our_values";
import { article as standing_by_our_values_russian } from "./standing_by_our_values_russian";
import { article as skins_now_in_modrinth_app } from "./skins_now_in_modrinth_app";
import { article as russian_censorship } from "./russian_censorship";
import { article as redesign } from "./redesign";
import { article as pride_campaign_2025 } from "./pride_campaign_2025";
import { article as plugins_resource_packs } from "./plugins_resource_packs";
import { article as new_site_beta } from "./new_site_beta";
import { article as new_environments } from "./new_environments";
import { article as modrinth_servers_beta } from "./modrinth_servers_beta";
import { article as modrinth_servers_asia } from "./modrinth_servers_asia";
import { article as modrinth_beta } from "./modrinth_beta";
import { article as modrinth_app_beta } from "./modrinth_app_beta";
import { article as modpacks_alpha } from "./modpacks_alpha";
import { article as modpack_changes } from "./modpack_changes";
import { article as licensing_guide } from "./licensing_guide";
import { article as knossos_v2_1_0 } from "./knossos_v2_1_0";
import { article as free_server_medal } from "./free_server_medal";
import { article as download_adjustment } from "./download_adjustment";
import { article as design_refresh } from "./design_refresh";
import { article as creator_updates_july_2025 } from "./creator_updates_july_2025";
import { article as creator_update } from "./creator_update";
import { article as creator_monetization } from "./creator_monetization";
import { article as carbon_ads } from "./carbon_ads";
import { article as capital_return } from "./capital_return";
import { article as becoming_sustainable } from "./becoming_sustainable";
import { article as accelerating_development } from "./accelerating_development";
import { article as a_new_chapter_for_modrinth_servers } from "./a_new_chapter_for_modrinth_servers";
import { article as two_years_of_modrinth } from "./two_years_of_modrinth";
import { article as two_years_of_modrinth_history } from "./two_years_of_modrinth_history";
import { article as whats_modrinth } from "./whats_modrinth";
import { article as windows_borderless_malware_disclosure } from "./windows_borderless_malware_disclosure";
export const articles = [
windows_borderless_malware_disclosure,

View File

@@ -3,12 +3,13 @@
<button
v-if="!!slots.title"
:class="buttonClass ?? 'flex flex-col gap-2 bg-transparent m-0 p-0 border-none'"
@click="() => (isOpen ? close() : open())"
@click="() => (forceOpen ? undefined : toggledOpen ? close() : open())"
>
<slot name="button" :open="isOpen">
<div class="flex items-center gap-1 w-full">
<slot name="title" />
<DropdownIcon
v-if="!forceOpen"
class="ml-auto size-5 transition-transform duration-300 shrink-0"
:class="{ 'rotate-180': isOpen }"
/>
@@ -28,7 +29,7 @@
<script setup lang="ts">
import { DropdownIcon } from '@modrinth/assets'
import { ref, useSlots } from 'vue'
import { computed, ref, useSlots } from 'vue'
const props = withDefaults(
defineProps<{
@@ -37,6 +38,7 @@ const props = withDefaults(
buttonClass?: string
contentClass?: string
titleWrapperClass?: string
forceOpen?: boolean
}>(),
{
type: 'standard',
@@ -44,27 +46,29 @@ const props = withDefaults(
buttonClass: null,
contentClass: null,
titleWrapperClass: null,
forceOpen: false,
},
)
const isOpen = ref(props.openByDefault)
const toggledOpen = ref(props.openByDefault)
const isOpen = computed(() => toggledOpen.value || props.forceOpen)
const emit = defineEmits(['onOpen', 'onClose'])
const slots = useSlots()
function open() {
isOpen.value = true
toggledOpen.value = true
emit('onOpen')
}
function close() {
isOpen.value = false
toggledOpen.value = false
emit('onClose')
}
defineExpose({
open,
close,
isOpen,
isOpen: toggledOpen,
})
defineOptions({

View File

@@ -5,9 +5,11 @@
:disabled="disabled"
:dropdown-id="dropdownId"
:tooltip="tooltip"
:placement="placement"
>
<slot></slot>
<template #menu>
<slot name="menu-header" />
<template v-for="(option, index) in options.filter((x) => x.shown === undefined || x.shown)">
<div
v-if="isDivider(option)"
@@ -96,12 +98,14 @@ withDefaults(
disabled?: boolean
dropdownId?: string
tooltip?: string
placement?: string
}>(),
{
options: () => [],
disabled: false,
dropdownId: undefined,
tooltip: undefined,
placement: 'bottom-end',
},
)

View File

@@ -3,7 +3,7 @@
ref="dropdown"
no-auto-focus
:aria-id="dropdownId || null"
placement="bottom-end"
:placement="placement"
:class="dropdownClass"
@apply-hide="focusTrigger"
@apply-show="focusMenuChild"
@@ -45,6 +45,11 @@ defineProps({
default: null,
required: false,
},
placement: {
type: String,
default: 'bottom-end',
required: false,
},
})
function focusMenuChild() {

View File

@@ -17,6 +17,9 @@
"button.cancel": {
"defaultMessage": "Cancel"
},
"button.clear": {
"defaultMessage": "Clear"
},
"button.close": {
"defaultMessage": "Close"
},

View File

@@ -25,6 +25,10 @@ export const commonMessages = defineMessages({
id: 'button.cancel',
defaultMessage: 'Cancel',
},
clearButton: {
id: 'button.clear',
defaultMessage: 'Clear',
},
closeButton: {
id: 'button.close',
defaultMessage: 'Close',