mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
Merge branch 'duckietm:main' into multicolorfurnifix
This commit is contained in:
@@ -24,10 +24,10 @@ export const LayoutGridItem: FC<LayoutGridItemProps> = props =>
|
|||||||
|
|
||||||
const getClassNames = useMemo(() =>
|
const getClassNames = useMemo(() =>
|
||||||
{
|
{
|
||||||
const newClassNames: string[] = [ 'layout-grid-item', 'border', 'border-2', 'border-[#c4cabf]', 'rounded-[6px]' ];
|
const newClassNames: string[] = [ 'layout-grid-item' ];
|
||||||
|
|
||||||
|
|
||||||
if(itemActive) newClassNames.push('bg-[#e4e7df]! border-[#aeb7aa]!');
|
if(itemActive) newClassNames.push('is-grid-active', 'bg-[#e4e7df]!');
|
||||||
|
|
||||||
if(itemUniqueSoldout || (itemUniqueNumber > 0)) newClassNames.push('unique-item');
|
if(itemUniqueSoldout || (itemUniqueNumber > 0)) newClassNames.push('unique-item');
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ interface CatalogGridOfferViewProps extends LayoutGridItemProps
|
|||||||
{
|
{
|
||||||
offer: IPurchasableOffer;
|
offer: IPurchasableOffer;
|
||||||
selectOffer: (offer: IPurchasableOffer) => void;
|
selectOffer: (offer: IPurchasableOffer) => void;
|
||||||
|
tintColor?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { offer = null, selectOffer = null, itemActive = false, ...rest } = props;
|
const { offer = null, selectOffer = null, itemActive = false, tintColor = null, ...rest } = props;
|
||||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||||
const { requestOfferToMover = null } = useCatalogActions();
|
const { requestOfferToMover = null } = useCatalogActions();
|
||||||
const { currentType = CatalogType.NORMAL } = useCatalogUiState();
|
const { currentType = CatalogType.NORMAL } = useCatalogUiState();
|
||||||
@@ -130,6 +131,7 @@ export const CatalogGridOfferView: FC<CatalogGridOfferViewProps> = props =>
|
|||||||
className="nitro-catalog-classic-grid-offer-icon"
|
className="nitro-catalog-classic-grid-offer-icon"
|
||||||
src={ iconUrl }
|
src={ iconUrl }
|
||||||
draggable={ false }
|
draggable={ false }
|
||||||
|
style={ tintColor ? { filter: 'url(#guild-furni-recolor)', transform: 'translateZ(0)' } : undefined }
|
||||||
onError={ event =>
|
onError={ event =>
|
||||||
{
|
{
|
||||||
const fallbackIconUrl = product.getIconUrl(offer);
|
const fallbackIconUrl = product.getIconUrl(offer);
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ export const CatalogLayoutDefaultView: FC<CatalogLayoutProps> = props =>
|
|||||||
<CatalogSpinnerWidgetView />
|
<CatalogSpinnerWidgetView />
|
||||||
</div>
|
</div>
|
||||||
<div className="nitro-catalog-classic-total-price-slot">
|
<div className="nitro-catalog-classic-total-price-slot">
|
||||||
|
<span className="nitro-catalog-classic-total-price-label">{ LocalizeText('catalog.bundlewidget.price') }</span>
|
||||||
<CatalogTotalPriceWidget />
|
<CatalogTotalPriceWidget />
|
||||||
</div>
|
</div>
|
||||||
</div> }
|
</div> }
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { FC } from 'react';
|
import { StringDataType } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { FaExchangeAlt, FaSyncAlt } from 'react-icons/fa';
|
import { FaExchangeAlt, FaSyncAlt } from 'react-icons/fa';
|
||||||
import { Column } from '../../../../../common';
|
import { Column } from '../../../../../common';
|
||||||
import { useCatalogData, useUserGroups } from '../../../../../hooks';
|
import { useCatalogData, useCatalogUiState, useUserGroups } from '../../../../../hooks';
|
||||||
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
import { CatalogFirstProductSelectorWidgetView } from '../widgets/CatalogFirstProductSelectorWidgetView';
|
||||||
import { CatalogGuildBadgeWidgetView } from '../widgets/CatalogGuildBadgeWidgetView';
|
import { CatalogGuildBadgeWidgetView } from '../widgets/CatalogGuildBadgeWidgetView';
|
||||||
|
import { CatalogGuildFurniRecolorFilter } from '../widgets/CatalogGuildFurniRecolorFilter';
|
||||||
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
import { CatalogGuildSelectorWidgetView } from '../widgets/CatalogGuildSelectorWidgetView';
|
||||||
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
import { CatalogItemGridWidgetView } from '../widgets/CatalogItemGridWidgetView';
|
||||||
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
|
||||||
@@ -14,11 +16,43 @@ import { CatalogLayoutProps } from './CatalogLayout.types';
|
|||||||
export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = () =>
|
export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = () =>
|
||||||
{
|
{
|
||||||
const { currentOffer = null, roomPreviewer = null } = useCatalogData();
|
const { currentOffer = null, roomPreviewer = null } = useCatalogData();
|
||||||
|
const { purchaseOptions = null } = useCatalogUiState();
|
||||||
const { data: groups = null } = useUserGroups();
|
const { data: groups = null } = useUserGroups();
|
||||||
const hasGroups = !!(groups && groups.length);
|
const hasGroups = !!(groups && groups.length);
|
||||||
|
const [ groupColors, setGroupColors ] = useState<{ colorA: string; colorB: string } | null>(null);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const previewStuffData = purchaseOptions?.previewStuffData ?? null;
|
||||||
|
|
||||||
|
if(!previewStuffData) return;
|
||||||
|
|
||||||
|
const colorA = (previewStuffData as StringDataType).getValue(3);
|
||||||
|
const colorB = (previewStuffData as StringDataType).getValue(4);
|
||||||
|
|
||||||
|
if(!colorA || !colorA.length) return;
|
||||||
|
|
||||||
|
const next = { colorA, colorB: (colorB && colorB.length) ? colorB : colorA };
|
||||||
|
|
||||||
|
setGroupColors(prev => (prev && (prev.colorA === next.colorA) && (prev.colorB === next.colorB)) ? prev : next);
|
||||||
|
}, [ purchaseOptions ]);
|
||||||
|
|
||||||
|
|
||||||
|
const tintColor = useMemo(() =>
|
||||||
|
{
|
||||||
|
if(!groupColors) return null;
|
||||||
|
|
||||||
|
const { colorA, colorB } = groupColors;
|
||||||
|
|
||||||
|
if(colorB && (colorB !== colorA)) return `linear-gradient(90deg, #${ colorA } 0 50%, #${ colorB } 50% 100%)`;
|
||||||
|
|
||||||
|
return `#${ colorA }`;
|
||||||
|
}, [ groupColors ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{ !!groupColors &&
|
||||||
|
<CatalogGuildFurniRecolorFilter colorA={ groupColors.colorA } colorB={ groupColors.colorB } /> }
|
||||||
<CatalogFirstProductSelectorWidgetView />
|
<CatalogFirstProductSelectorWidgetView />
|
||||||
<Column fullHeight gap={ 1 } overflow="hidden">
|
<Column fullHeight gap={ 1 } overflow="hidden">
|
||||||
{ !!currentOffer &&
|
{ !!currentOffer &&
|
||||||
@@ -38,7 +72,7 @@ export const CatalogLayouGuildCustomFurniView: FC<CatalogLayoutProps> = () =>
|
|||||||
</div>
|
</div>
|
||||||
</div> }
|
</div> }
|
||||||
<div className="grow! min-h-0 overflow-auto">
|
<div className="grow! min-h-0 overflow-auto">
|
||||||
<CatalogItemGridWidgetView columnCount={ 5 } columnMinWidth={ 36 } />
|
<CatalogItemGridWidgetView className="nitro-catalog-classic-grid" columnCount={ 6 } columnMinHeight={ 80 } columnMinWidth={ 55 } tintColor={ tintColor } />
|
||||||
</div>
|
</div>
|
||||||
{ !!currentOffer &&
|
{ !!currentOffer &&
|
||||||
<div className="flex shrink-0 flex-col gap-1">
|
<div className="flex shrink-0 flex-col gap-1">
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ export const CatalogLayouGuildForumView: FC<CatalogLayoutProps> = props =>
|
|||||||
</div>
|
</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
{ hasGroups &&
|
{ hasGroups &&
|
||||||
<CatalogPurchaseWidgetView noGiftOption={ true } /> }
|
<div className="flex justify-center">
|
||||||
|
<CatalogPurchaseWidgetView noGiftOption={ true } />
|
||||||
|
</div> }
|
||||||
</div> }
|
</div> }
|
||||||
</Column>
|
</Column>
|
||||||
<Column alignItems="center" overflow="hidden" size={ 4 }>
|
<Column alignItems="center" overflow="hidden" size={ 4 }>
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { memo, useMemo } from 'react';
|
||||||
|
|
||||||
|
interface CatalogGuildFurniRecolorFilterProps
|
||||||
|
{
|
||||||
|
colorA?: string;
|
||||||
|
colorB?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GUILD_FURNI_RECOLOR_FILTER_ID = 'guild-furni-recolor';
|
||||||
|
const OUTLINE_LEVEL = 0.08;
|
||||||
|
|
||||||
|
const toUnit = (hex: string, offset: number): number =>
|
||||||
|
{
|
||||||
|
const value = parseInt(hex.substr(offset, 2), 16);
|
||||||
|
|
||||||
|
return (isNaN(value) ? 0 : value) / 255;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CatalogGuildFurniRecolorFilter = memo((props: CatalogGuildFurniRecolorFilterProps) =>
|
||||||
|
{
|
||||||
|
const { colorA = null, colorB = null } = props;
|
||||||
|
|
||||||
|
const tables = useMemo(() =>
|
||||||
|
{
|
||||||
|
if(!colorA || (colorA.length < 6) || !colorB || (colorB.length < 6)) return null;
|
||||||
|
|
||||||
|
const aR = toUnit(colorA, 0), aG = toUnit(colorA, 2), aB = toUnit(colorA, 4);
|
||||||
|
const bR = toUnit(colorB, 0), bG = toUnit(colorB, 2), bB = toUnit(colorB, 4);
|
||||||
|
|
||||||
|
return {
|
||||||
|
r: `${ OUTLINE_LEVEL } ${ bR } ${ bR } ${ aR } ${ aR } ${ aR }`,
|
||||||
|
g: `${ OUTLINE_LEVEL } ${ bG } ${ bG } ${ aG } ${ aG } ${ aG }`,
|
||||||
|
b: `${ OUTLINE_LEVEL } ${ bB } ${ bB } ${ aB } ${ aB } ${ aB }`
|
||||||
|
};
|
||||||
|
}, [ colorA, colorB ]);
|
||||||
|
|
||||||
|
if(!tables) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg aria-hidden="true" focusable="false" width="0" height="0" style={ { position: 'absolute', width: 0, height: 0 } }>
|
||||||
|
<filter id={ GUILD_FURNI_RECOLOR_FILTER_ID } colorInterpolationFilters="sRGB">
|
||||||
|
<feComponentTransfer>
|
||||||
|
<feFuncR type="table" tableValues={ tables.r } />
|
||||||
|
<feFuncG type="table" tableValues={ tables.g } />
|
||||||
|
<feFuncB type="table" tableValues={ tables.b } />
|
||||||
|
</feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
CatalogGuildFurniRecolorFilter.displayName = 'CatalogGuildFurniRecolorFilter';
|
||||||
@@ -7,12 +7,12 @@ import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
|
|||||||
|
|
||||||
interface CatalogItemGridWidgetViewProps extends AutoGridProps
|
interface CatalogItemGridWidgetViewProps extends AutoGridProps
|
||||||
{
|
{
|
||||||
|
tintColor?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = props =>
|
export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { columnCount = 5, children = null, ...rest } = props;
|
const { columnCount = 5, tintColor = null, children = null, ...rest } = props;
|
||||||
const { currentOffer = null, currentPage = null } = useCatalogData();
|
const { currentOffer = null, currentPage = null } = useCatalogData();
|
||||||
const { selectCatalogOffer = null } = useCatalogActions();
|
const { selectCatalogOffer = null } = useCatalogActions();
|
||||||
const catalogAdmin = useCatalogAdmin();
|
const catalogAdmin = useCatalogAdmin();
|
||||||
@@ -26,13 +26,6 @@ export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = pro
|
|||||||
if(elementRef && elementRef.current) elementRef.current.scrollTop = 0;
|
if(elementRef && elementRef.current) elementRef.current.scrollTop = 0;
|
||||||
}, [ currentPage ]);
|
}, [ currentPage ]);
|
||||||
|
|
||||||
// Drag-and-drop handlers — hooks MUST run unconditionally so the
|
|
||||||
// hook order stays stable when currentPage flips from null to a
|
|
||||||
// real value (the `if(!currentPage) return null` below would
|
|
||||||
// otherwise hide these from the first render and React would flag
|
|
||||||
// "Rendered more hooks than during the previous render"). Bodies
|
|
||||||
// are safe to evaluate pre-load: currentPage? optional chaining
|
|
||||||
// already guards the only access inside handleDrop.
|
|
||||||
const handleDragStart = useCallback((index: number) =>
|
const handleDragStart = useCallback((index: number) =>
|
||||||
{
|
{
|
||||||
setDragIndex(index);
|
setDragIndex(index);
|
||||||
@@ -96,6 +89,7 @@ export const CatalogItemGridWidgetView: FC<CatalogItemGridWidgetViewProps> = pro
|
|||||||
itemActive={ (currentOffer && (currentOffer.offerId === offer.offerId)) }
|
itemActive={ (currentOffer && (currentOffer.offerId === offer.offerId)) }
|
||||||
offer={ offer }
|
offer={ offer }
|
||||||
selectOffer={ selectOffer }
|
selectOffer={ selectOffer }
|
||||||
|
tintColor={ tintColor }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -827,40 +827,45 @@
|
|||||||
overflow: visible !important;
|
overflow: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .layout-grid-item {
|
@layer utilities {
|
||||||
width: 100% !important;
|
.nitro-catalog-classic-window .layout-grid-item {
|
||||||
height: var(--nitro-grid-column-min-height, 70px) !important;
|
width: 100% !important;
|
||||||
min-width: 0 !important;
|
height: var(--nitro-grid-column-min-height, 70px) !important;
|
||||||
min-height: var(--nitro-grid-column-min-height, 70px) !important;
|
min-width: 0 !important;
|
||||||
border: 0 !important;
|
min-height: var(--nitro-grid-column-min-height, 70px) !important;
|
||||||
border-radius: 0 !important;
|
border: 0 !important;
|
||||||
background-image: none !important;
|
border-radius: 0 !important;
|
||||||
box-shadow: none !important;
|
background-image: none !important;
|
||||||
overflow: visible !important;
|
box-shadow: none !important;
|
||||||
}
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .layout-grid-item:not(.has-highlight) {
|
.nitro-catalog-classic-window .layout-grid-item:not(.has-highlight) {
|
||||||
background-color: transparent !important;
|
background-color: #e4e7df !important;
|
||||||
}
|
border: 2px solid transparent !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .nitro-catalog-classic-pet-breeds .layout-grid-item {
|
.nitro-catalog-classic-window .nitro-catalog-classic-pet-breeds .layout-grid-item {
|
||||||
width: 84px !important;
|
width: 84px !important;
|
||||||
min-width: 84px !important;
|
min-width: 84px !important;
|
||||||
height: 74px !important;
|
height: 74px !important;
|
||||||
min-height: 74px !important;
|
min-height: 74px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .layout-grid-item:hover {
|
.nitro-catalog-classic-window .layout-grid-item:not(.has-highlight):not(.is-active):hover {
|
||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
box-shadow: inset 0 0 0 1px #a1a19b !important;
|
border-color: transparent !important;
|
||||||
}
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .layout-grid-item.is-active {
|
.nitro-catalog-classic-window .layout-grid-item.is-active {
|
||||||
background-image: none !important;
|
background-color: #ffffff !important;
|
||||||
box-shadow:
|
background-image: none !important;
|
||||||
inset 0 0 0 1px #63c5e9,
|
border: 2px solid #62c4e8 !important;
|
||||||
inset 2px 2px 0 #ecece4,
|
box-shadow: none !important;
|
||||||
inset -2px -2px 0 #ecece4 !important;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window .layout-grid-item.has-highlight {
|
.nitro-catalog-classic-window .layout-grid-item.has-highlight {
|
||||||
@@ -901,13 +906,15 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.nitro-catalog-classic-grid-price {
|
.nitro-catalog-classic-grid-price {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-end;
|
||||||
gap: 3px;
|
gap: 3px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding-right: 4px;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -963,7 +970,8 @@
|
|||||||
.nitro-catalog-classic-grid-price.is-multi-price {
|
.nitro-catalog-classic-grid-price.is-multi-price {
|
||||||
height: auto;
|
height: auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
row-gap: 1px;
|
row-gap: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,7 +979,7 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 1px;
|
gap: 3px;
|
||||||
height: 13px;
|
height: 13px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -1022,8 +1030,7 @@
|
|||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-total-price-slot::before {
|
.nitro-catalog-classic-total-price-label {
|
||||||
content: "Prezzo";
|
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
@@ -1463,9 +1470,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nitro-catalog-classic-window *::-webkit-scrollbar-thumb {
|
.nitro-catalog-classic-window *::-webkit-scrollbar-thumb {
|
||||||
/* Grip: a single 2px #a0a0a0 stripe in an 8px-wide centered band,
|
|
||||||
repeated every 5px (2px stripe + 3px body gap).
|
|
||||||
Outline: 1px black border, then a 2px white inset frame inside it. */
|
|
||||||
min-height: 24px !important;
|
min-height: 24px !important;
|
||||||
background:
|
background:
|
||||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5'><rect x='0' y='0' width='8' height='2' fill='%23a0a0a0'/></svg>") center top / 8px 5px repeat-y,
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5'><rect x='0' y='0' width='8' height='2' fill='%23a0a0a0'/></svg>") center top / 8px 5px repeat-y,
|
||||||
@@ -1487,9 +1491,6 @@
|
|||||||
#bcbcbc !important;
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Arrow buttons: light grey cap with rounded OUTER corners (up button
|
|
||||||
rounded at the top, down button rounded at the bottom), 1px black
|
|
||||||
border, dark chevron via inline SVG. */
|
|
||||||
.nitro-catalog-classic-window *::-webkit-scrollbar-button:single-button:vertical:decrement {
|
.nitro-catalog-classic-window *::-webkit-scrollbar-button:single-button:vertical:decrement {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
width: 18px !important;
|
width: 18px !important;
|
||||||
@@ -1606,13 +1607,6 @@
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stack the navigation above the furni/preview layout and let the
|
|
||||||
whole content area scroll. The previous grid used
|
|
||||||
`grid-template-rows: auto minmax(0, 1fr)`, but on iOS Safari the
|
|
||||||
flex height chain is indefinite, so the 1fr layout-shell row
|
|
||||||
collapsed to 0 and only the sidebar (category list) was visible.
|
|
||||||
A flex column sized to content + a scrollable content-shell is
|
|
||||||
device-robust. */
|
|
||||||
.nitro-catalog-classic-stage,
|
.nitro-catalog-classic-stage,
|
||||||
.nitro-catalog-classic-stage.is-navigation-hidden {
|
.nitro-catalog-classic-stage.is-navigation-hidden {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1628,9 +1622,6 @@
|
|||||||
max-height: 30vh;
|
max-height: 30vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The default layout's children (preview, grid, buy bar) are
|
|
||||||
absolutely positioned against a fixed ~460px box, so give the
|
|
||||||
shell a definite height and never clip it on mobile. */
|
|
||||||
.nitro-catalog-classic-layout-shell {
|
.nitro-catalog-classic-layout-shell {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
+85
-60
@@ -116,97 +116,128 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
*::-webkit-scrollbar {
|
||||||
width: 17px !important;
|
width: 18px !important;
|
||||||
height: 17px !important;
|
height: 18px !important;
|
||||||
|
background-color: #bdbbb3 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar:horizontal {
|
*::-webkit-scrollbar:horizontal {
|
||||||
height: 17px !important;
|
height: 18px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar:not(:horizontal) {
|
*::-webkit-scrollbar:not(:horizontal) {
|
||||||
width: 17px !important;
|
width: 18px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* App-wide Habbo scrollbar (sprites cropped from catalog_skin1.png).
|
|
||||||
Thumb sprite is 17x34 with caps + grip baked in; stretched full
|
|
||||||
height via background-size: 17px 100%. Arrow buttons are natural
|
|
||||||
17x16 sprites. */
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-track {
|
*::-webkit-scrollbar-track {
|
||||||
background-color: #e7e5d8 !important;
|
|
||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
box-shadow: inset 1px 0 0 #b9b6a5, inset -1px 0 0 #ffffff !important;
|
background-color: #bdbbb3 !important;
|
||||||
|
box-shadow: inset 1px 0 0 #000000 !important;
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
*::-webkit-scrollbar-thumb {
|
||||||
min-height: 24px !important;
|
min-height: 24px !important;
|
||||||
background-color: transparent !important;
|
background:
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_thumb.png") !important;
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5'><rect x='0' y='0' width='8' height='2' fill='%23a0a0a0'/></svg>") center top / 8px 5px repeat-y,
|
||||||
background-repeat: no-repeat !important;
|
#d9d9d9 !important;
|
||||||
background-position: center center !important;
|
border: 1px solid #000000 !important;
|
||||||
background-size: 17px 100% !important;
|
border-radius: 3px !important;
|
||||||
border: 0 !important;
|
box-shadow: inset 0 0 0 2px #ffffff !important;
|
||||||
border-radius: 0 !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
image-rendering: pixelated !important;
|
image-rendering: pixelated !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb:hover,
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5'><rect x='0' y='0' width='8' height='2' fill='%23ababab'/></svg>") center top / 8px 5px repeat-y,
|
||||||
|
#e3e3e3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb:active {
|
*::-webkit-scrollbar-thumb:active {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_thumb_pressed.png") !important;
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='5'><rect x='0' y='0' width='8' height='2' fill='%23606060'/></svg>") center top / 8px 5px repeat-y,
|
||||||
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-corner {
|
*::-webkit-scrollbar-corner {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-button:single-button {
|
|
||||||
display: block !important;
|
|
||||||
width: 17px !important;
|
|
||||||
height: 16px !important;
|
|
||||||
/* Cream fill so the arrow sprite's transparent rounded corners
|
|
||||||
paint over the track colour, not whatever is behind the
|
|
||||||
scrollbar (which can render black). */
|
|
||||||
background-color: #e7e5d8 !important;
|
|
||||||
background-repeat: no-repeat !important;
|
|
||||||
background-position: center !important;
|
|
||||||
border: 0 !important;
|
|
||||||
image-rendering: pixelated !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-button:single-button:vertical:decrement {
|
*::-webkit-scrollbar-button:single-button:vertical:decrement {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_up.png") !important;
|
display: block !important;
|
||||||
|
width: 18px !important;
|
||||||
|
height: 18px !important;
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6'><polygon points='4.5,0 9,6 0,6' fill='%23222'/></svg>") center center / 9px 6px no-repeat,
|
||||||
|
#d9d9d9 !important;
|
||||||
|
border: 1px solid #000000 !important;
|
||||||
|
border-radius: 3px 3px 0 0 !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 #ffffff,
|
||||||
|
inset 1px 0 0 rgba(255, 255, 255, 0.6) !important;
|
||||||
}
|
}
|
||||||
*::-webkit-scrollbar-button:single-button:vertical:decrement:active {
|
*::-webkit-scrollbar-button:single-button:vertical:decrement:active {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_up_pressed.png") !important;
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6'><polygon points='4.5,0 9,6 0,6' fill='%23000'/></svg>") center center / 9px 6px no-repeat,
|
||||||
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-button:single-button:vertical:increment {
|
*::-webkit-scrollbar-button:single-button:vertical:increment {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_down.png") !important;
|
display: block !important;
|
||||||
|
width: 18px !important;
|
||||||
|
height: 18px !important;
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6'><polygon points='0,0 9,0 4.5,6' fill='%23222'/></svg>") center center / 9px 6px no-repeat,
|
||||||
|
#d9d9d9 !important;
|
||||||
|
border: 1px solid #000000 !important;
|
||||||
|
border-radius: 0 0 3px 3px !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 #ffffff,
|
||||||
|
inset 1px 0 0 rgba(255, 255, 255, 0.6) !important;
|
||||||
}
|
}
|
||||||
*::-webkit-scrollbar-button:single-button:vertical:increment:active {
|
*::-webkit-scrollbar-button:single-button:vertical:increment:active {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_v_down_pressed.png") !important;
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='9' height='6'><polygon points='0,0 9,0 4.5,6' fill='%23000'/></svg>") center center / 9px 6px no-repeat,
|
||||||
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-button:single-button:horizontal:decrement {
|
*::-webkit-scrollbar-button:single-button:horizontal:decrement {
|
||||||
width: 16px !important;
|
display: block !important;
|
||||||
height: 17px !important;
|
width: 18px !important;
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_h_left.png") !important;
|
height: 18px !important;
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='9'><polygon points='0,4.5 6,0 6,9' fill='%23222'/></svg>") center center / 6px 9px no-repeat,
|
||||||
|
#d9d9d9 !important;
|
||||||
|
border: 1px solid #000000 !important;
|
||||||
|
border-radius: 3px 0 0 3px !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 #ffffff,
|
||||||
|
inset 1px 0 0 rgba(255, 255, 255, 0.6) !important;
|
||||||
}
|
}
|
||||||
*::-webkit-scrollbar-button:single-button:horizontal:decrement:active {
|
*::-webkit-scrollbar-button:single-button:horizontal:decrement:active {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_h_left_pressed.png") !important;
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='9'><polygon points='0,4.5 6,0 6,9' fill='%23000'/></svg>") center center / 6px 9px no-repeat,
|
||||||
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-button:single-button:horizontal:increment {
|
*::-webkit-scrollbar-button:single-button:horizontal:increment {
|
||||||
width: 16px !important;
|
display: block !important;
|
||||||
height: 17px !important;
|
width: 18px !important;
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_h_right.png") !important;
|
height: 18px !important;
|
||||||
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='9'><polygon points='6,4.5 0,0 0,9' fill='%23222'/></svg>") center center / 6px 9px no-repeat,
|
||||||
|
#d9d9d9 !important;
|
||||||
|
border: 1px solid #000000 !important;
|
||||||
|
border-radius: 0 3px 3px 0 !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 #ffffff,
|
||||||
|
inset 1px 0 0 rgba(255, 255, 255, 0.6) !important;
|
||||||
}
|
}
|
||||||
*::-webkit-scrollbar-button:single-button:horizontal:increment:active {
|
*::-webkit-scrollbar-button:single-button:horizontal:increment:active {
|
||||||
background-image: url("../assets/images/catalog/scrollbar/scroll_h_right_pressed.png") !important;
|
background:
|
||||||
|
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='9'><polygon points='6,4.5 0,0 0,9' fill='%23000'/></svg>") center center / 6px 9px no-repeat,
|
||||||
|
#bcbcbc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
@@ -714,6 +745,12 @@ body {
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-color: #cdd3d9;
|
background-color: #cdd3d9;
|
||||||
|
border: 2px solid #c4cabf;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-grid-item.is-grid-active {
|
||||||
|
border-color: #aeb7aa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-friends-spritesheet {
|
.nitro-friends-spritesheet {
|
||||||
@@ -816,8 +853,6 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avatar editor icons are now rendered as <img> tags via AvatarEditorIcon.tsx */
|
|
||||||
|
|
||||||
.nitro-avatar-editor-wardrobe-figure-preview {
|
.nitro-avatar-editor-wardrobe-figure-preview {
|
||||||
background-color: #677181;
|
background-color: #677181;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -940,10 +975,9 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Font Size */
|
|
||||||
|
|
||||||
.fs-custom {
|
.fs-custom {
|
||||||
font-size: var(--font-size, 16px); /* Fallback to 16px if not set */
|
font-size: var(--font-size, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-wired {
|
.nitro-wired {
|
||||||
@@ -1898,8 +1932,6 @@ body {
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Avatar Editor ─────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
.color-picker-frame {
|
.color-picker-frame {
|
||||||
border-image-source: url('@/assets/images/avatareditor/color_frame.png');
|
border-image-source: url('@/assets/images/avatareditor/color_frame.png');
|
||||||
border-image-slice: 6 6 6 6 fill;
|
border-image-slice: 6 6 6 6 fill;
|
||||||
@@ -1977,8 +2009,6 @@ body {
|
|||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Avatar Editor tab icons ───────────────────────────────────────────── */
|
|
||||||
|
|
||||||
.avatar-editor-tabs {
|
.avatar-editor-tabs {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@@ -2045,11 +2075,6 @@ body {
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Avatar Editor misc ─────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
|
|
||||||
/* ── Pet Companion ─────────────────────────────────────────────────────── */
|
|
||||||
|
|
||||||
.pet-equipped-bar {
|
.pet-equipped-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user