From 6466ce3c2cd46163267df8970191933dbde5fc8b Mon Sep 17 00:00:00 2001 From: Bob Lee Date: Wed, 29 Jul 2026 22:02:31 -0700 Subject: [PATCH] fix(web): unify MiniApp market typography and alignment The submission workspace defined its own sizes and paddings instead of reusing the gallery/form primitives, so the section headings sat indented past the fields below them, hints rendered at three different sizes (a few still relying on the browser's 80% default), and the textarea's box did not match the inputs it sat between. Everything in the view now follows one scale borrowed from the existing components: 13px/600 section titles, 12px muted hints, 13px/500 field labels, 13px values. Concretely: - Section headings put the icon inline with the title so the title, the description and every field below share one left edge. - Selects and inputs use the components' own `label` prop instead of hand-rolled labels, with a shared 6px label-to-control gap. - The textarea copies .bitfun-input-container's box (transparent, base border, 12px inset, focus ring) so carets line up across fields. - The screenshot row no longer space-betweens three children; copy sits left, the two buttons group right. - The form is capped at a 620px measure instead of stretching to 1360px. - Submission history rendered the icon *name* as text in a 32px box; it now renders the icon. The market detail modal picks up the same title/body scale. --- .../miniapps/views/MiniAppMarketView.scss | 7 +- .../views/MiniAppSubmissionsView.scss | 250 ++++++++++++------ .../miniapps/views/MiniAppSubmissionsView.tsx | 128 ++++----- 3 files changed, 238 insertions(+), 147 deletions(-) diff --git a/src/web-ui/src/app/scenes/miniapps/views/MiniAppMarketView.scss b/src/web-ui/src/app/scenes/miniapps/views/MiniAppMarketView.scss index 0f67f3205f..dbfc189655 100644 --- a/src/web-ui/src/app/scenes/miniapps/views/MiniAppMarketView.scss +++ b/src/web-ui/src/app/scenes/miniapps/views/MiniAppMarketView.scss @@ -86,7 +86,9 @@ strong { overflow: hidden; + color: var(--color-text-primary); font-size: var(--font-size-base); + font-weight: $font-weight-semibold; text-overflow: ellipsis; white-space: nowrap; } @@ -142,15 +144,18 @@ margin: 0; } + // Same scale as the submission workspace: 13px/600 titles over 13px body. h4 { + color: var(--color-text-primary); font-size: var(--font-size-sm); + font-weight: $font-weight-semibold; } p, li { color: var(--color-text-secondary); font-size: var(--font-size-sm); - line-height: 1.55; + line-height: $line-height-relaxed; } } diff --git a/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.scss b/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.scss index a823ac74d3..b075de092b 100644 --- a/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.scss +++ b/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.scss @@ -1,6 +1,16 @@ @use '../../../../component-library/styles/tokens' as *; +// One typographic scale for the whole submission workspace, borrowed from the +// gallery/form primitives so nothing in here invents its own size: +// section title 13px / 600 / primary — .gallery-zone__title +// section hint 12px / 400 / muted — .gallery-zone__subtitle +// field label 13px / 500 / secondary — .bitfun-input-label +// field value 13px / 400 / primary — .select__value +// inline hint 12px / 400 / muted — .bitfun-input-hint .miniapp-submissions { + // Label-to-control distance, shared by Input, Select and the textarea fields. + --submissions-label-gap: 6px; + // Match GalleryLayout's $content-max / $gutter so switching tabs inside the // MiniApp scene doesn't shift content horizontally. &__workspace, @@ -9,6 +19,22 @@ margin-inline: auto; } + // The shared Input renders its value at 14px while Select renders 13px; pin + // both to 13px so every control in the form reads at the same size. + .bitfun-input-container { + font-size: var(--font-size-sm); + } + + .select__label { + margin-bottom: var(--submissions-label-gap); + } + + // Select's trigger is shrink-to-fit by default; stretch it so the dropdown + // lines up with the inputs above and below it. + .select__trigger { + width: 100%; + } + &__loading { display: grid; min-height: 360px; @@ -23,20 +49,27 @@ padding: 0 clamp(28px, 4vw, 64px) $size-gap-3; color: var(--color-warning); font-size: var(--font-size-sm); + + svg { + flex: 0 0 auto; + } } &__workspace { display: grid; - grid-template-columns: minmax(0, 1.25fr) minmax(310px, 0.75fr); + // Cap the form at a readable measure instead of letting single-line inputs + // stretch the full 1360px, and keep the history pinned to the right edge. + grid-template-columns: minmax(0, 620px) minmax(280px, 380px); + justify-content: space-between; gap: $size-gap-5; - padding: $size-gap-2 clamp(28px, 4vw, 64px) 56px; + padding: $size-gap-3 clamp(28px, 4vw, 64px) 56px; } &__form, &__history { align-content: start; display: grid; - gap: $size-gap-3; + gap: $size-gap-4; } &__history { @@ -45,15 +78,8 @@ } &__section-heading { - display: flex; - align-items: flex-start; - gap: $size-gap-2; - margin-bottom: $size-gap-1; - - svg { - margin-top: 2px; - color: var(--color-text-muted); - } + display: grid; + gap: 3px; h3, p { @@ -61,14 +87,23 @@ } h3 { - font-size: var(--font-size-base); + display: flex; + align-items: center; + gap: $size-gap-2; + color: var(--color-text-primary); + font-size: var(--font-size-sm); + font-weight: $font-weight-semibold; + + svg { + flex: 0 0 auto; + color: var(--color-text-muted); + } } p { - margin-top: 3px; - color: var(--color-text-secondary); - font-size: var(--font-size-sm); - line-height: 1.45; + color: var(--color-text-muted); + font-size: var(--font-size-xs); + line-height: $line-height-relaxed; } } @@ -80,60 +115,89 @@ &__field { display: grid; - gap: $size-gap-1; + gap: var(--submissions-label-gap); > span { - color: var(--color-text-primary); + color: var(--color-text-secondary); font-size: var(--font-size-sm); - font-weight: 500; + font-weight: $font-weight-medium; + letter-spacing: 0.2px; } textarea { width: 100%; min-height: 92px; - padding: 9px 10px; - border: 1px solid var(--border-subtle); - border-radius: $size-radius-base; + // Same box as .bitfun-input-container so the caret lines up with the + // single-line fields above it. + padding: 8px 12px; + border: 1px solid var(--border-base); + border-radius: $size-radius-sm; outline: none; - background: var(--element-bg-soft); + background: transparent; color: var(--color-text-primary); - line-height: 1.5; + font-family: inherit; + font-size: var(--font-size-sm); + line-height: $line-height-base; resize: vertical; + transition: + border-color $motion-fast ease, + box-shadow $motion-fast ease; + + &::placeholder { + color: color-mix(in srgb, var(--color-text-muted) 40%, var(--color-bg-primary)); + } + + &:hover:not(:disabled) { + border-color: var(--border-strong); + } &:focus { border-color: var(--color-accent-500); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent-500) 14%, transparent); } &:disabled { - cursor: not-allowed; - opacity: 0.55; + cursor: default; + opacity: var(--opacity-disabled); } } } &__screenshots { display: flex; - align-items: center; + align-items: flex-end; justify-content: space-between; gap: $size-gap-3; - padding-top: $size-gap-2; + padding-top: $size-gap-3; border-top: 1px solid var(--border-subtle); + } - > div { - display: grid; - gap: 3px; + &__screenshots-copy { + display: grid; + gap: 3px; + min-width: 0; - > span { - font-size: var(--font-size-sm); - font-weight: 500; - } + span { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + font-weight: $font-weight-medium; + letter-spacing: 0.2px; + } - small { - color: var(--color-text-muted); - } + small { + color: var(--color-text-muted); + font-size: var(--font-size-xs); + line-height: $line-height-relaxed; } } + &__screenshots-actions { + display: flex; + align-items: center; + flex: 0 0 auto; + gap: $size-gap-2; + } + &__files { display: grid; gap: 6px; @@ -142,13 +206,17 @@ display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; - gap: 8px; - padding: 7px 9px; - border-radius: $size-radius-base; + gap: $size-gap-2; + padding: 7px 10px; + border-radius: $size-radius-sm; background: var(--element-bg-soft); color: var(--color-text-secondary); font-size: var(--font-size-sm); + svg { + color: var(--color-text-muted); + } + span { overflow: hidden; text-overflow: ellipsis; @@ -159,9 +227,9 @@ display: grid; padding: 3px; border: 0; - border-radius: $size-radius-base; + border-radius: $size-radius-sm; background: transparent; - color: inherit; + color: var(--color-text-muted); cursor: pointer; place-items: center; @@ -176,13 +244,13 @@ &__advanced-toggle { display: flex; align-items: center; - gap: $size-gap-1; + gap: $size-gap-2; padding: 0; border: 0; background: transparent; color: var(--color-text-secondary); font-size: var(--font-size-sm); - font-weight: 500; + font-weight: $font-weight-medium; cursor: pointer; justify-self: start; max-width: 100%; @@ -193,12 +261,14 @@ svg { flex: 0 0 auto; + color: var(--color-text-muted); } small { overflow: hidden; color: var(--color-text-muted); - font-weight: 400; + font-size: var(--font-size-xs); + font-weight: $font-weight-normal; text-overflow: ellipsis; white-space: nowrap; } @@ -207,22 +277,28 @@ &__advanced { display: grid; gap: $size-gap-3; - padding-left: $size-gap-3; - border-left: 2px solid var(--border-subtle); + padding-left: $size-gap-4; + border-left: 1px solid var(--border-subtle); } &__progress { display: grid; gap: 7px; padding: 10px 12px; - border-radius: $size-radius-base; + border-radius: $size-radius-sm; background: var(--element-bg-soft); - div { + > div { display: flex; justify-content: space-between; color: var(--color-text-secondary); - font-size: var(--font-size-sm); + font-size: var(--font-size-xs); + } + + strong { + color: var(--color-text-primary); + font-weight: $font-weight-medium; + font-variant-numeric: tabular-nums; } progress { @@ -239,49 +315,49 @@ article { display: grid; gap: $size-gap-2; - padding: 14px 0; + padding: $size-gap-3 0; border-bottom: 1px solid var(--border-subtle); + } + } - > div:first-child { - display: flex; - align-items: center; - gap: $size-gap-2; + &__list-head { + display: flex; + align-items: center; + gap: $size-gap-2; - > div { - display: grid; - min-width: 0; - gap: 3px; - } + > div { + display: grid; + min-width: 0; + gap: 2px; + } - strong, - small { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + strong, + small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } - small { - color: var(--color-text-muted); - } - } + strong { + color: var(--color-text-primary); + font-size: var(--font-size-sm); + font-weight: $font-weight-semibold; + } - > p { - margin: 0; - color: var(--color-warning); - font-size: var(--font-size-sm); - line-height: 1.45; - } + small { + color: var(--color-text-muted); + font-size: var(--font-size-xs); } } &__app-icon { display: grid; - width: 34px; - height: 34px; + width: 32px; + height: 32px; flex: 0 0 auto; - border: 1px solid var(--border-subtle); - border-radius: $size-radius-base; + border-radius: $size-radius-sm; background: var(--element-bg-soft); + color: var(--color-text-primary); place-items: center; } @@ -289,6 +365,14 @@ display: flex; align-items: center; justify-content: space-between; + gap: $size-gap-2; + } + + &__rejection { + margin: 0; + color: var(--color-warning); + font-size: var(--font-size-xs); + line-height: $line-height-relaxed; } &__history-empty { @@ -303,7 +387,7 @@ @media (max-width: 860px) { .miniapp-submissions { &__workspace { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } &__history { diff --git a/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.tsx b/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.tsx index 4a0c27bfff..27df562418 100644 --- a/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.tsx +++ b/src/web-ui/src/app/scenes/miniapps/views/MiniAppSubmissionsView.tsx @@ -7,6 +7,7 @@ import { ChevronRight, FileImage, Github, + History, Loader2, PackageOpen, RefreshCw, @@ -32,6 +33,7 @@ import { useNotification } from '@/shared/notification-system'; import { createLogger } from '@/shared/utils/logger'; import { useSceneManager } from '@/app/hooks/useSceneManager'; import type { SceneTabId } from '@/app/components/SceneBar/types'; +import { renderMiniAppIcon } from '../utils/miniAppIcons'; import './MiniAppSubmissionsView.scss'; const log = createLogger('MiniAppSubmissionsView'); @@ -309,26 +311,24 @@ const MiniAppSubmissionsView: React.FC = () => {
void submit(event)}> -
- -
-

{t('market.submissions.newTitle')}

-

{t('market.submissions.newHint')}

-
-
- -
-
+
{t('market.submissions.screenshots')} {t('market.submissions.screenshotHint')}
- - +
+ + +
{screenshotPaths.length ? (
@@ -445,18 +447,16 @@ const MiniAppSubmissionsView: React.FC = () => {
-