From 6022911448f82d5b9beb0a81d12d47eeabb5ef33 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Tue, 26 May 2026 19:26:07 +0200 Subject: [PATCH 1/3] fix(toolbar): bump desktop layout breakpoint to 1700px to avoid icon clip The left-nav container is `max-w-[calc(50vw-242px)]` (reserves the chat frame width) and uses `overflow-x: clip`. With the full icon set (habbo, rooms, game, catalog, buildersclub, inventory, ME, wired-tools, camera, youtube, modtools, furnieditor, housekeeping) the icons exceed the available 528-608px around the 1540-1700px viewport range, so the last icons get silently clipped on the right. Raising the desktop breakpoint from 1540px to 1700px makes the client fall back to the mobile-scrollable layout (`.tb-bar-scroll`) below 1700px, which scrolls horizontally and doesn't clip. Above 1700px the desktop fixed-icon layout still applies, now with enough horizontal room for every icon even with mod+HK enabled. Touch devices are unaffected (already forced onto the mobile layout via `pointer: coarse`). --- src/components/toolbar/ToolbarView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/toolbar/ToolbarView.tsx b/src/components/toolbar/ToolbarView.tsx index edf59e6..8bec8e3 100644 --- a/src/components/toolbar/ToolbarView.tsx +++ b/src/components/toolbar/ToolbarView.tsx @@ -69,10 +69,10 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => toggleTimeoutRef.current = setTimeout(() => { toggleLockRef.current = false; }, TOGGLE_LOCK_MS); }, []); - const compactFramePosition = (isToolbarOpen && isInRoom) ? 'bottom-[90px] min-[1540px]:bottom-0' : 'bottom-0'; - const mobileOnlyClasses = isTouchLayout ? '' : 'min-[1540px]:hidden'; - const desktopBlockClasses = isTouchLayout ? 'hidden' : 'hidden min-[1540px]:block'; - const desktopFlexClasses = isTouchLayout ? 'hidden' : 'hidden min-[1540px]:flex'; + const compactFramePosition = (isToolbarOpen && isInRoom) ? 'bottom-[90px] min-[1700px]:bottom-0' : 'bottom-0'; + const mobileOnlyClasses = isTouchLayout ? '' : 'min-[1700px]:hidden'; + const desktopBlockClasses = isTouchLayout ? 'hidden' : 'hidden min-[1700px]:block'; + const desktopFlexClasses = isTouchLayout ? 'hidden' : 'hidden min-[1700px]:flex'; const leftNavVariants = useMemo(() => ({ hidden: { opacity: 0, x: isInRoom ? -10 : 0, y: isInRoom ? 0 : 8, pointerEvents: 'none' }, visible: { opacity: 1, x: 0, y: 0, pointerEvents: 'auto' } From b1244cbd5afe7a47d410255a75fce75202425007 Mon Sep 17 00:00:00 2001 From: duckietm Date: Wed, 27 May 2026 13:42:11 +0200 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=86=99=20Fix=20BOTS=20in=20catalog=20?= =?UTF-8?q?and=20inventory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/layout/LayoutAvatarImageView.tsx | 50 +++++++++++++++---- .../page/common/CatalogGridOfferView.tsx | 2 +- .../page/layout/CatalogLayoutDefaultView.tsx | 4 +- .../views/bot/InventoryBotItemView.tsx | 4 +- .../inventory/views/bot/InventoryBotView.tsx | 2 +- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/common/layout/LayoutAvatarImageView.tsx b/src/common/layout/LayoutAvatarImageView.tsx index 75233a8..bd640e2 100644 --- a/src/common/layout/LayoutAvatarImageView.tsx +++ b/src/common/layout/LayoutAvatarImageView.tsx @@ -12,35 +12,51 @@ export interface LayoutAvatarImageViewProps extends BaseProps headOnly?: boolean; direction?: number; scale?: number; + fit?: boolean; } export const LayoutAvatarImageView: FC = props => { - const { figure = '', gender = '', headOnly = false, direction = 0, scale = 1, classNames = [], style = {}, ...rest } = props; + const { figure = '', gender = '', headOnly = false, direction = 0, scale = 1, fit = false, classNames = [], style = {}, ...rest } = props; const [ avatarUrl, setAvatarUrl ] = useState(null); const [ isReady, setIsReady ] = useState(false); const isDisposed = useRef(false); - // Request id bumped on every prop change. The SDK can call - // resetFigure asynchronously when server-side figure data lands; - // if props change in quick succession the older callback could - // otherwise overwrite the newer image. The closure captures the - // id and bails when stale. const requestIdRef = useRef(0); const getClassNames = useMemo(() => { - const newClassNames: string[] = [ 'avatar-image relative w-[90px] h-[130px] bg-no-repeat left-[-2px] pointer-events-none' ]; + let newClassNames: string[]; + + if(fit) + { + newClassNames = [ 'avatar-image absolute inset-0 pointer-events-none' ]; + } + else if(headOnly) + { + newClassNames = [ 'avatar-image absolute inset-0 bg-no-repeat pointer-events-none' ]; + } + else + { + newClassNames = [ 'avatar-image relative w-[90px] h-[130px] bg-no-repeat left-[-2px] pointer-events-none' ]; + } if(classNames.length) newClassNames.push(...classNames); return newClassNames; - }, [ classNames ]); + }, [ classNames, headOnly, fit ]); const getStyle = useMemo(() => { let newStyle: CSSProperties = {}; - if(avatarUrl && avatarUrl.length) newStyle.backgroundImage = `url('${ avatarUrl }')`; + if(!fit && avatarUrl && avatarUrl.length) newStyle.backgroundImage = `url('${ avatarUrl }')`; + + if(headOnly && !fit) + { + newStyle.backgroundSize = '130px auto'; + newStyle.backgroundPosition = '51% 40%'; + newStyle.imageRendering = 'pixelated'; + } if(scale !== 1) { @@ -52,7 +68,7 @@ export const LayoutAvatarImageView: FC = props => if(Object.keys(style).length) newStyle = { ...newStyle, ...style }; return newStyle; - }, [ avatarUrl, scale, style ]); + }, [ avatarUrl, scale, style, headOnly, fit ]); useEffect(() => { @@ -116,5 +132,17 @@ export const LayoutAvatarImageView: FC = props => }; }, []); - return ; + return ( + + { fit && avatarUrl && avatarUrl.length > 0 && ( + + ) } + + ); }; diff --git a/src/components/catalog/views/page/common/CatalogGridOfferView.tsx b/src/components/catalog/views/page/common/CatalogGridOfferView.tsx index 936b8dc..6fa45ba 100644 --- a/src/components/catalog/views/page/common/CatalogGridOfferView.tsx +++ b/src/components/catalog/views/page/common/CatalogGridOfferView.tsx @@ -76,7 +76,7 @@ export const CatalogGridOfferView: FC = props => { iconUrl && !(offer.product.productType === ProductTypeEnum.ROBOT) &&
} { (offer.product.productType === ProductTypeEnum.ROBOT) && - } + }
diff --git a/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx b/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx index dd55268..3490e60 100644 --- a/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx +++ b/src/components/catalog/views/page/layout/CatalogLayoutDefaultView.tsx @@ -88,7 +88,6 @@ export const CatalogLayoutDefaultView: FC = props =>
} - { /* Welcome/description card */ } { !currentOffer &&
{ !!page.localization.getImage(1) && @@ -96,11 +95,10 @@ export const CatalogLayoutDefaultView: FC = props =>
} - { /* Item grid */ }
{ GetConfigurationValue('catalog.headers') && } - +
); diff --git a/src/components/inventory/views/bot/InventoryBotItemView.tsx b/src/components/inventory/views/bot/InventoryBotItemView.tsx index 9a084cf..4a48485 100644 --- a/src/components/inventory/views/bot/InventoryBotItemView.tsx +++ b/src/components/inventory/views/bot/InventoryBotItemView.tsx @@ -38,8 +38,8 @@ export const InventoryBotItemView: FC - + + { children } ); diff --git a/src/components/inventory/views/bot/InventoryBotView.tsx b/src/components/inventory/views/bot/InventoryBotView.tsx index 87b8adf..2882ea0 100644 --- a/src/components/inventory/views/bot/InventoryBotView.tsx +++ b/src/components/inventory/views/bot/InventoryBotView.tsx @@ -68,7 +68,7 @@ export const InventoryBotView: FC<{
- columnCount={ 6 } + columnCount={ 4 } itemRender={ item => } items={ botItems } />
From 00fbdc6f6dfc95751872e50e207546a7000852c4 Mon Sep 17 00:00:00 2001 From: duckietm Date: Wed, 27 May 2026 15:37:09 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=86=99=20Small=20update=20toolbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/toolbar/ToolbarView.tsx | 88 +++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/components/toolbar/ToolbarView.tsx b/src/components/toolbar/ToolbarView.tsx index 8bec8e3..6bcc9a3 100644 --- a/src/components/toolbar/ToolbarView.tsx +++ b/src/components/toolbar/ToolbarView.tsx @@ -216,14 +216,6 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => CreateLinkEvent('catalog/toggle/normal') } className="tb-icon" /> - - CreateLinkEvent('catalog/toggle/builder') } className="tb-icon" /> - - - CreateLinkEvent('inventory/toggle') } className="tb-icon" /> - { (getFullCount > 0) && - } - { isMeExpanded && @@ -237,7 +229,7 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => } @@ -245,11 +237,19 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => setMeExpanded(value => !value); event.stopPropagation(); } }> - + { (getTotalUnseen > 0) && } + + CreateLinkEvent('catalog/toggle/builder') } className="tb-icon" /> + + + CreateLinkEvent('inventory/toggle') } className="tb-icon" /> + { (getFullCount > 0) && + } + { (isInRoom && showToolbarButton) && @@ -268,14 +268,14 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => { (openTicketsCount > 0) && } } - { isMod && - - CreateLinkEvent('furni-editor/toggle') } className="tb-icon" /> - } { (isHk && hkEnabled) && CreateLinkEvent('housekeeping/toggle') } className="tb-icon" /> } + { isMod && + + CreateLinkEvent('furni-editor/toggle') } className="tb-icon" /> + } = props => CreateLinkEvent('catalog/toggle/normal') } className="tb-icon" /> + + + { isMeExpanded && + + + } + + + { + setMeExpanded(value => !value); + event.stopPropagation(); + } }> + + + { (getTotalUnseen > 0) && + } + CreateLinkEvent('catalog/toggle/builder') } className="tb-icon" /> @@ -333,32 +359,6 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => } - - - { isMeExpanded && - - - } - - - { - setMeExpanded(value => !value); - event.stopPropagation(); - } }> - - - { (getTotalUnseen > 0) && - } - @@ -380,14 +380,14 @@ export const ToolbarView: FC<{ isInRoom: boolean }> = props => { (openTicketsCount > 0) && } } - { isMod && - - CreateLinkEvent('furni-editor/toggle') } className="tb-icon" /> - } { (isHk && hkEnabled) && CreateLinkEvent('housekeeping/toggle') } className="tb-icon" /> } + { isMod && + + CreateLinkEvent('furni-editor/toggle') } className="tb-icon" /> + } CreateLinkEvent('friends/toggle') } className="tb-icon" /> { (requests.length > 0) &&