refactor: Button components (#6929)

* feat: refactor button components

* fix: qa

* fix: storybook

* a11y: pass

* fix: build

* fix: rename default ->md

* fix: lint

* docs: buttons.md

* refactor part 1

* refactor part 2

* fix: undo refactor for fresh restart

* refactor

* Revert "refactor"

This reverts commit 96d65902d7.

* refactor: part 1

* fix: qa

* fix: qa

* fix: qa

* fix: qa

* fix: qa

* fix: qa

* fix: qa

* fix: qa

* fix: remove text-contrast

* fix: qa

* fix: v-tooltip

* fix: lint

* fix: split broken

* fix: passkey qa

* fix: qa

* fix: qa

* fix: prepr

* fix: splitbutton

* improve button group seam

---------

Signed-off-by: Calum H. <calum@modrinth.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
Calum H.
2026-08-04 13:54:04 -07:00
committed by GitHub
co-authored by Prospector
parent 6cfe999cb3
commit bb2193b6f5
398 changed files with 13688 additions and 13133 deletions
@@ -22,9 +22,9 @@ import {
XIcon,
} from '@modrinth/assets'
import { type TechReviewContext, techReviewQuickReplies } from '@modrinth/moderation'
import { Button, ButtonLink, IconButton, TeleportOverflowMenu } from '@modrinth/ui'
import {
Avatar,
ButtonStyled,
Collapsible,
CollapsibleRegion,
commonMessages,
@@ -32,7 +32,6 @@ import {
injectModrinthClient,
injectNotificationManager,
NavTabs,
OverflowMenu,
type OverflowMenuOption,
Toggle,
useFormatBytes,
@@ -120,29 +119,32 @@ const isLoadingStatusAction = ref(false)
const projectStatusActions = computed<OverflowMenuOption[]>(() => [
{
id: 'approve',
color: 'green',
action: () => setStatus('approved'),
label: 'Approve',
tone: 'green',
hoverFilled: true,
action: () => setStatus('approved'),
disabled: isStatusActionDisabled('approved'),
},
{
id: 'withhold',
color: 'orange',
action: () => setStatus('withheld'),
label: 'Withhold',
tone: 'orange',
hoverFilled: true,
action: () => setStatus('withheld'),
disabled: isStatusActionDisabled('withheld'),
},
{
id: 'send-to-review',
label: 'Send to review',
action: () => setStatus('processing'),
hoverFilled: true,
disabled: isStatusActionDisabled('processing'),
},
{
id: 'reject',
color: 'red',
action: () => setStatus('rejected'),
label: 'Reject',
tone: 'red',
hoverFilled: true,
action: () => setStatus('rejected'),
disabled: isStatusActionDisabled('rejected'),
},
])
@@ -1495,29 +1497,26 @@ function copyId() {
<div class="flex items-center gap-3">
<span class="text-base text-secondary">{{ formattedDate }}</span>
<div class="flex items-center gap-2">
<ButtonStyled v-if="props.item.project.link_urls?.['source']?.url" circular>
<a
v-tooltip="'Open sources in new tab'"
:href="props.item.project.link_urls?.['source']?.url"
target="_blank"
>
<CodeIcon />
</a>
</ButtonStyled>
<ButtonStyled circular>
<button v-tooltip="'Copy ID'" @click="copyId">
<ClipboardCopyIcon />
</button>
</ButtonStyled>
<ButtonStyled circular>
<a
v-tooltip="'Open in new tab'"
:href="`/moderation/technical-review/${props.item.project.id}`"
target="_blank"
>
<ExternalIcon />
</a>
</ButtonStyled>
<ButtonLink
v-if="props.item.project.link_urls?.['source']?.url"
v-tooltip="'Open sources in new tab'"
:href="props.item.project.link_urls?.['source']?.url"
target="_blank"
class="!w-9 !rounded-full !px-0"
>
<CodeIcon />
</ButtonLink>
<IconButton v-tooltip="'Copy ID'" :label="'Copy ID'" @click="copyId">
<ClipboardCopyIcon />
</IconButton>
<ButtonLink
v-tooltip="'Open in new tab'"
:href="`/moderation/technical-review/${props.item.project.id}`"
target="_blank"
class="!w-9 !rounded-full !px-0"
>
<ExternalIcon />
</ButtonLink>
</div>
</div>
</div>
@@ -1552,58 +1551,60 @@ function copyId() {
@update-thread="handleThreadUpdate"
>
<template #additionalActions>
<ButtonStyled color="brand">
<button
v-tooltip="!canSubmitReview ? 'There are still pending flags!' : undefined"
:disabled="!canSubmitReview"
@click="handleSubmitReview('safe')"
>
<ShieldCheckIcon /> Pass
</button>
</ButtonStyled>
<ButtonStyled color="red">
<button
v-tooltip="!canSubmitReview ? 'There are still pending flags!' : undefined"
:disabled="!canSubmitReview"
@click="handleSubmitReview('unsafe')"
>
<BugIcon /> Fail
</button>
</ButtonStyled>
<ButtonStyled color="standard">
<OverflowMenu
class="btn-dropdown-animation"
:disabled="isLoadingStatusAction"
:options="projectStatusActions"
>
<SpinnerIcon
v-if="isLoadingStatusAction"
class="animate-spin"
aria-hidden="true"
/>
<ScaleIcon v-else aria-hidden="true" />
Set Status
<template #approve>
<CheckIcon aria-hidden="true" />
Approve
</template>
<template #withhold>
<EyeOffIcon aria-hidden="true" />
Withhold
</template>
<template #send-to-review>
<ScaleIcon aria-hidden="true" />
Send to review
</template>
<template #reject>
<XIcon aria-hidden="true" />
Reject
</template>
</OverflowMenu>
</ButtonStyled>
<ButtonStyled v-if="featureFlags.developerMode" type="outlined">
<button @click="emit('showMaliciousSummary', unsafeFiles)">Debug</button>
</ButtonStyled>
<Button
v-tooltip="!canSubmitReview ? 'There are still pending flags!' : undefined"
type="colored"
color="brand"
:disabled="!canSubmitReview"
@click="handleSubmitReview('safe')"
>
<ShieldCheckIcon /> Pass
</Button>
<Button
v-tooltip="!canSubmitReview ? 'There are still pending flags!' : undefined"
type="colored"
color="red"
:disabled="!canSubmitReview"
@click="handleSubmitReview('unsafe')"
>
<BugIcon /> Fail
</Button>
<TeleportOverflowMenu
label="More options"
class="btn-dropdown-animation !w-auto !rounded-xl !px-2.5"
:disabled="isLoadingStatusAction"
:options="projectStatusActions"
>
<SpinnerIcon
v-if="isLoadingStatusAction"
class="animate-spin"
aria-hidden="true"
/>
<ScaleIcon v-else aria-hidden="true" />
Set Status
<template #approve>
<CheckIcon aria-hidden="true" />
Approve
</template>
<template #withhold>
<EyeOffIcon aria-hidden="true" />
Withhold
</template>
<template #send-to-review>
<ScaleIcon aria-hidden="true" />
Send to review
</template>
<template #reject>
<XIcon aria-hidden="true" />
Reject
</template>
</TeleportOverflowMenu>
<Button
v-if="featureFlags.developerMode"
type="outlined"
@click="emit('showMaliciousSummary', unsafeFiles)"
>Debug</Button
>
</template>
</ThreadView>
</div>
@@ -1674,19 +1675,16 @@ function copyId() {
</div>
<div class="flex items-center gap-2">
<ButtonStyled v-if="getFileDetailCount(file) > 0">
<button @click="viewFileFlags(file)">Flags</button>
</ButtonStyled>
<ButtonStyled type="outlined">
<a
:href="file.download_url"
:title="`Download ${file.file_name}`"
:download="file.file_name"
tabindex="0"
>
<DownloadIcon /> Download
</a>
</ButtonStyled>
<Button v-if="getFileDetailCount(file) > 0" @click="viewFileFlags(file)">Flags</Button>
<ButtonLink
type="outlined"
:href="file.download_url"
:title="`Download ${file.file_name}`"
:download="file.file_name"
tabindex="0"
>
<DownloadIcon /> Download
</ButtonLink>
</div>
</div>
</template>
@@ -1856,14 +1854,14 @@ function copyId() {
@click="toggleClass(classItem)"
>
<div class="my-auto flex items-center gap-2">
<ButtonStyled type="transparent" circular>
<button
class="transition-transform"
:class="{ 'rotate-180': expandedClasses.has(classItem.key) }"
>
<ChevronDownIcon class="h-5 w-5 text-contrast" />
</button>
</ButtonStyled>
<IconButton
type="quiet"
label="Toggle details"
class="transition-transform"
:class="{ 'rotate-180': expandedClasses.has(classItem.key) }"
>
<ChevronDownIcon class="h-5 w-5 text-contrast" />
</IconButton>
<span v-tooltip="classItem.filePath" class="font-mono font-semibold">{{
truncateMiddle(classItem.filePath)
@@ -2061,16 +2059,16 @@ function copyId() {
v-if="getHighlightedClassSource(classItem).length > 0"
class="relative inset-0 overflow-hidden rounded-lg border border-solid border-surface-5 bg-surface-4"
>
<ButtonStyled circular type="transparent">
<button
v-tooltip="`Copy code`"
class="absolute right-2 top-2 border-[1px]"
@click="copyToClipboard(getClassDecompiledSource(classItem)!, classItem.key)"
>
<CopyIcon v-if="!showCopyFeedback.get(classItem.key)" />
<CheckIcon v-else />
</button>
</ButtonStyled>
<IconButton
v-tooltip="`Copy code`"
type="quiet"
:label="`Copy code`"
class="absolute right-2 top-2 border-[1px]"
@click="copyToClipboard(getClassDecompiledSource(classItem)!, classItem.key)"
>
<CopyIcon v-if="!showCopyFeedback.get(classItem.key)" />
<CheckIcon v-else />
</IconButton>
<div class="overflow-x-auto bg-surface-3 py-3">
<div