fix(explore/ui): kill shell overflow, white-on-white values, broken Menu button (v1.1.11)

Three write-once-deploy-4 root causes from the 4-res audit:

1. Horizontal overflow (454px @1280, 38px @1920). The shared layout
   Container forced 'min-w-[100vw] lg:min-w-[fit-content]', promoting the
   whole page to its ~1734px max-content width so stat/block cards clipped
   past the viewport. Make it a fluid column ('w-full min-w-0') and add
   'min-w-0' to MainColumn so the flex chain shrinks and inner
   overflow-x-auto regions scroll internally -> document.scrollWidth ==
   innerWidth at every breakpoint.

2. White-on-white values (block Reward / tx Value / tx Fee /
   network-utilization%). These passed legacy Chakra dot-tokens
   ('text.secondary', 'green.600'...) straight into an inline CSS 'color',
   which browsers drop as invalid -> the text inherited white. Add one
   resolveColorToken() helper (dot-token -> var(--color-*)), apply it in
   SimpleValue (the value chokepoint for Reward/Value/Fee), and point
   getNetworkUtilizationParams at real theme vars (bright badge fg shades,
   all >=4.5:1 on the light card bg).

3. Broken 'Menu' button: the wallet/settings button stacked a 20px icon
   over its label in a bare div inside a 32px overflow-hidden button (the
   '51px in 32px' clip that read as a stray hamburger at lg+). Lay the
   icon+label out horizontally (flex items-center gap-2, sized icon).

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-07-19 01:24:19 -07:00
co-authored by Hanzo Dev
parent 712a0394e5
commit 6d805a016a
8 changed files with 48 additions and 19 deletions
@@ -20,7 +20,7 @@ spec:
imagePullSecrets: [{name: ghcr-luxfi}]
containers:
- name: explore
image: ghcr.io/luxfi/explore:v1.1.10
image: ghcr.io/luxfi/explore:v1.1.11
imagePullPolicy: IfNotPresent
ports: [{containerPort: 3000, name: ui}]
env:
@@ -81,7 +81,7 @@ spec:
imagePullSecrets: [{name: ghcr-luxfi}]
containers:
- name: explore
image: ghcr.io/zooai/explore:v1.1.10
image: ghcr.io/zooai/explore:v1.1.11
imagePullPolicy: IfNotPresent
ports: [{containerPort: 3000, name: ui}]
env:
@@ -142,7 +142,7 @@ spec:
imagePullSecrets: [{name: ghcr-luxfi}]
containers:
- name: explore
image: ghcr.io/hanzoai/explore:v1.1.10
image: ghcr.io/hanzoai/explore:v1.1.11
imagePullPolicy: IfNotPresent
ports: [{containerPort: 3000, name: ui}]
env:
@@ -203,7 +203,7 @@ spec:
imagePullSecrets: [{name: ghcr-luxfi}]
containers:
- name: explore
image: ghcr.io/parsdao/explore:v1.1.10
image: ghcr.io/parsdao/explore:v1.1.11
imagePullPolicy: IfNotPresent
ports: [{containerPort: 3000, name: ui}]
env:
+8 -3
View File
@@ -11,10 +11,15 @@ export default function getNetworkUtilizationParams(value: number) {
return 'low';
})();
// Theme CSS vars (defined in styles/tokens.css for both light + dark). The
// previous Chakra dot-tokens (red.600 etc.) had no matching --color-*-600 var,
// so they rendered as invalid CSS and the % inherited white-on-white. The
// "bright" badge foregrounds are the darkest semantic status shades and clear
// 4.5:1 on the light card background.
const colors = {
high: 'red.600',
medium: 'orange.600',
low: 'green.600',
high: 'var(--color-badge-bright-red-fg)',
medium: 'var(--color-badge-bright-orange-fg)',
low: 'var(--color-badge-bright-green-fg)',
};
const color = colors[load];
+16
View File
@@ -0,0 +1,16 @@
// Resolve a legacy Chakra dot-notation color token (e.g. "text.secondary",
// "green.600") to the CSS custom property the theme actually defines, so it
// renders as a real color instead of an invalid `color: text.secondary` that
// the browser drops (which made values inherit white-on-white).
//
// Anything already valid CSS is passed through untouched: var(...), #hex,
// rgb(...)/hsl(...), a named color, or any bare word with no dot.
export function resolveColorToken(color?: string): string | undefined {
if (!color) {
return undefined;
}
if (!color.includes('.')) {
return color;
}
return `var(--color-${ color.replace(/\./g, '-') })`;
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@luxfi/explore",
"version": "1.1.10",
"version": "1.1.11",
"private": false,
"homepage": "https://github.com/luxfi/explore#readme",
"engines": {
+1 -1
View File
@@ -9,7 +9,7 @@ interface Props {
const Container = ({ children, className }: Props) => {
return (
<div className={ cn('min-w-[100vw] lg:min-w-[fit-content] mx-auto bg-[var(--color-bg-primary)]', className) }>
<div className={ cn('w-full min-w-0 mx-auto bg-[var(--color-bg-primary)]', className) }>
{ children }
</div>
);
+1 -1
View File
@@ -15,7 +15,7 @@ const MainColumn = ({ children, className }: Props) => {
<div
className={ cn(
'flex flex-col grow pt-[12px] lg:pt-6 pb-8',
'w-full',
'w-full min-w-0',
isHorizontal ? 'lg:w-full' : 'lg:w-auto',
isHorizontal ? 'px-4 lg:px-6' : 'px-4 lg:px-8',
'2xl:px-6',
+11 -3
View File
@@ -1,8 +1,9 @@
import { Skeleton } from '@luxfi/ui/skeleton';
import { Tooltip } from '@luxfi/ui/tooltip';
import type BigNumber from 'bignumber.js';
import React from 'react';
import { Skeleton } from '@luxfi/ui/skeleton';
import { Tooltip } from '@luxfi/ui/tooltip';
import { resolveColorToken } from 'lib/utils/colorToken';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import { DEFAULT_ACCURACY, formatBnValue } from './utils';
@@ -58,7 +59,14 @@ const SimpleValue = ({
}, [ postfix, prefix, value, tooltipContentBefore ]);
return (
<Skeleton loading={ loading } display="inline-flex" alignItems="center" color={ color } className="whitespace-pre max-w-full overflow-hidden" { ...rest }>
<Skeleton
loading={ loading }
display="inline-flex"
alignItems="center"
color={ resolveColorToken(color) }
className="whitespace-pre max-w-full overflow-hidden"
{ ...rest }
>
{ startElement }
<Tooltip
content={ tooltipContentProp ?? tooltipContent }
+6 -6
View File
@@ -1,9 +1,9 @@
import { Button, type ButtonProps } from '@luxfi/ui/button';
import { Tooltip } from '@luxfi/ui/tooltip';
import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile';
import shortenString from 'lib/shortenString';
import { Button, type ButtonProps } from '@luxfi/ui/button';
import { Tooltip } from '@luxfi/ui/tooltip';
import IconSvg from 'ui/shared/IconSvg';
import UserIdenticon from '../UserIdenticon';
@@ -25,16 +25,16 @@ const UserWalletButton = ({ size, variant, isPending, isAutoConnectDisabled, add
if (address) {
const text = domain || shortenString(address);
return (
<div>
<div className="flex items-center gap-2 min-w-0">
<UserIdenticon address={ address } isAutoConnectDisabled={ isAutoConnectDisabled }/>
<div>{ text }</div>
<div className="truncate">{ text }</div>
</div>
);
}
return (
<div>
<IconSvg name="profile"/>
<div className="flex items-center gap-2">
<IconSvg name="profile" className="w-5 h-5 shrink-0"/>
<div>Menu</div>
</div>
);