# NitroCard attuali

Questo file contiene una preview HTML modificabile e una copia esatta del codice sorgente attuale delle card nel progetto.

## Preview

Primary Card
Tab 1
Tab 2
Tab 3

Questo blocco riproduce la struttura visiva attuale delle NitroCard del progetto.

Header blu, tabs grigie e content area chiara.

Slim Card

Versione slim con header a righe come nel CSS attuale.

## Snapshot codice attuale

Nitro-V3/src/common/card/NitroCardView.tsx import { FC, useMemo, useRef } from 'react'; import { Column, ColumnProps } from '..'; import { DraggableWindow, DraggableWindowPosition, DraggableWindowProps } from '../draggable-window'; import { NitroCardContextProvider } from './NitroCardContext'; export interface NitroCardViewProps extends DraggableWindowProps, ColumnProps { theme?: string; isResizable?: boolean; } export const NitroCardView: FC<NitroCardViewProps> = props => { const { theme = 'primary', uniqueKey = null, handleSelector = '.drag-handler', windowPosition = DraggableWindowPosition.CENTER, disableDrag = false, overflow = 'hidden', position = 'relative', gap = 0, classNames = [], isResizable = true, ...rest } = props; const elementRef = useRef<HTMLDivElement>(); const getClassNames = useMemo(() => { const newClassNames: string[] = [ isResizable ? 'resize' : 'resize-none', 'rounded', 'shadow' ]; // Card Theme Changer newClassNames.push('border border-[#283F5D]'); if(classNames.length) newClassNames.push(...classNames); return newClassNames; }, [ classNames, isResizable ]); return ( <NitroCardContextProvider value={ { theme } }> <DraggableWindow disableDrag={ disableDrag } handleSelector={ handleSelector } uniqueKey={ uniqueKey } windowPosition={ windowPosition }> <Column classNames={ getClassNames } gap={ gap } innerRef={ elementRef } overflow={ overflow } position={ position } { ...rest } /> </DraggableWindow> </NitroCardContextProvider> ); };
Nitro-V3/src/common/card/NitroCardHeaderView.tsx import { FC, MouseEvent } from 'react'; import { FaFlag } from 'react-icons/fa'; import { Base, Column, ColumnProps, Flex } from '..'; interface NitroCardHeaderViewProps extends ColumnProps { headerText: string; isGalleryPhoto?: boolean; noCloseButton?: boolean; isInfoToHabboPages?: boolean; onReportPhoto?: (event: MouseEvent) => void; onClickInfoHabboPages?: (event: MouseEvent) => void; onCloseClick: (event: MouseEvent) => void; } export const NitroCardHeaderView: FC<NitroCardHeaderViewProps> = props => { const { headerText = null, isGalleryPhoto = false, noCloseButton = false, isInfoToHabboPages = false, onReportPhoto = null, onClickInfoHabboPages = null, onCloseClick = null, justifyContent = 'center', alignItems = 'center', classNames = [], children = null, ...rest } = props; const onMouseDown = (event: MouseEvent<HTMLDivElement>) => { event.stopPropagation(); event.nativeEvent.stopImmediatePropagation(); }; return ( <Column center className={ 'relative flex items-center justify-center flex-col drag-handler min-h-card-header max-h-card-header bg-card-header' } { ...rest }> <Flex center fullWidth> <span className="text-xl text-white drop-shadow-lg">{ headerText }</span> { isGalleryPhoto && <Base className="inset-e-4 nitro-card-header-report-camera" position="absolute" onClick={ onReportPhoto }> <FaFlag className="fa-icon" /> </Base> } { isInfoToHabboPages && <Base className="absolute right-8 nitro-card-header-info-habbopages cursor-pointer" position="absolute" onClick={ onClickInfoHabboPages } /> } <div className="absolute flex items-center justify-center cursor-pointer right-2 p-[2px] ubuntu-close-button" onClick={ onCloseClick } onMouseDownCapture={ onMouseDown }> </div> </Flex> </Column> ); };
Nitro-V3/src/common/card/NitroCardContentView.tsx import { FC, useMemo } from 'react'; import { Column, ColumnProps } from '..'; export const NitroCardContentView: FC<ColumnProps> = props => { const { overflow = 'auto', classNames = [], ...rest } = props; const getClassNames = useMemo(() => { // Theme Changer const newClassNames: string[] = [ 'container-fluid', 'h-full p-[8px] overflow-auto', 'bg-light' ]; if(classNames.length) newClassNames.push(...classNames); return newClassNames; }, [ classNames ]); return <Column classNames={ getClassNames } overflow={ overflow } { ...rest } />; };
Nitro-V3/src/common/card/tabs/NitroCardTabsView.tsx import { FC, useMemo } from 'react'; import { Flex, FlexProps } from '../..'; export const NitroCardTabsView: FC<FlexProps> = props => { const { justifyContent = 'center', gap = 1, classNames = [], children = null, ...rest } = props; const getClassNames = useMemo(() => { const newClassNames: string[] = [ 'justify-center gap-0.5 flex bg-card-tabs min-h-card-tabs max-h-card-tabs pt-1 border-b border-card-border px-2 -mt-px' ]; if(classNames.length) newClassNames.push(...classNames); return newClassNames; }, [ classNames ]); return ( <Flex classNames={ getClassNames } gap={ gap } justifyContent={ justifyContent } { ...rest }> { children } </Flex> ); };
Nitro-V3/src/common/card/tabs/NitroCardTabsItemView.tsx import { FC, useMemo } from 'react'; import { Flex, FlexProps } from '../../Flex'; import { LayoutItemCountView } from '../../layout'; interface NitroCardTabsItemViewProps extends FlexProps { isActive?: boolean; count?: number; } export const NitroCardTabsItemView: FC<NitroCardTabsItemViewProps> = props => { const { isActive = false, count = 0, overflow = 'hidden', position = 'relative', pointer = true, classNames = [], children = null, ...rest } = props; const getClassNames = useMemo(() => { const newClassNames: string[] = [ 'overflow-hidden relative cursor-pointer rounded-t-md flex bg-card-tab-item px-3 py-1 z-1 border-card-border border-t border-l border-r before:absolute before:w-[93%] before:h-[3px] before:rounded-md before:top-[1.5px] before:left-0 before:right-0 before:m-auto before:z-1 before:bg-[#C2C9D1]', isActive && 'bg-card-tab-item-active -mb-px before:bg-white' ]; //if (isActive) newClassNames.push('bg-[#dfdfdf] border-b-[1px_solid_black]'); if(classNames.length) newClassNames.push(...classNames); return newClassNames; }, [ isActive, classNames ]); return ( <Flex classNames={ getClassNames } overflow={ overflow } pointer={ pointer } position={ position } { ...rest }> <Flex center shrink> { children } </Flex> { (count > 0) && <LayoutItemCountView count={ count } /> } </Flex> ); };
Nitro-V3/src/css/nitrocard/NitroCardView.css .nitro-card { resize: both; @include media-breakpoint-down(lg) { max-width: 100vw !important; max-height: 100vh !important; } &.theme-primary { border: 1px solid #283F5D; .nitro-card-header { min-height: 33px; max-height: 33px; background: #1E7295; .nitro-card-header-text { color: #FFF; text-shadow: 0px 4px 4px rgba(#000, 0.25); @include font-size(1.35); } .nitro-card-header-close { cursor: pointer; padding: 2px 2px; line-height: 1; border-radius: .25rem; box-shadow: 0 0 0 1.6px #FFF; border: 2px solid #921911; background: repeating-linear-gradient( rgba(245, 80, 65, 1), rgba(245, 80, 65, 1) 50%, rgba(194, 48, 39, 1) 50%, rgba(194, 48, 39, 1) 100% ); &:hover { filter: brightness(1.2); } &:active { filter: brightness(0.8); } } .nitro-card-header-report-camera { cursor: pointer; padding: 1px 3px; line-height: 1; border-radius: .25rem; box-shadow: 0 0 0 1.6px #FFF; border: 2px solid #921911; background: repeating-linear-gradient( rgba(245, 80, 65, 1), rgba(245, 80, 65, 1) 50%, rgba(194, 48, 39, 1) 50%, rgba(194, 48, 39, 1) 100% ); &:hover { filter: brightness(1.2); } &:active { filter: brightness(0.8); } } } .nitro-card-tabs { background-color: #185D79; .nav-item { padding: .2rem .8rm; background-color: #B6BEC5; color: #000; z-index: 1; margin-bottom: -1px; &.active { background-color: #DFDFDF; border-color: #283F5D #283F5D #DFDFDF !important; border-bottom: 1px solid black; &:before { background: #FFF; } } &:before { content: ''; position: absolute; width: 93%; height: 3px; border-radius: 0.25rem; top: 1.5px; left: 0; right: 0; margin: auto; background: #c2c9d1; z-index: 1; } } } .content-area { background-color: #DFDFDF; } } &.theme-primary-slim { border: 1px solid #283F5D; .nitro-card-header { position: relative; min-height: 28px; max-height: 28px; background: repeating-linear-gradient(#2DABC2, #2DABC2 50%, #2B91A7 50%, #2B91A7 100%); border-bottom: 2px solid darken(#2B91A7, 5); box-shadow: 0 2px white; width: 100%; margin: 0; padding-top:2px; &:before { position: absolute; content: ' '; top: 0; left: 0; width: 100%; height: 2px; background-color: rgba(#FFF, 0.3); } .nitro-card-header-text { color: #FFF; text-shadow: 0px 4px 4px rgba(#000, 0.25); @include font-size (1.125); min-height: 21px; } .nitro-card-header-close { cursor: pointer; padding: 0px 2px; line-height: 1; @include font-size(.675); border-radius: .25rem; box-shadow: 0 0 0 1.6px #FFF; border: 2px solid #921911; background: repeating-linear-gradient( rgba(245, 80, 65, 1), rgba(245, 80, 65, 1) 50%, rgba(194, 48, 39, 1) 50%, rgba(194, 48, 39, 1) 100% ); &:hover { filter: brightness(1.2); } &:active { filter: brightness(0.8); } } .nitro-card-header-report-camera { cursor: pointer; padding: 0px 2px; margin-right: 4px; line-height: 1; @include font-size(.675); border-radius: .25rem; box-shadow: 0 0 0 1.6px #FFF; border: 2px solid #921911; background: repeating-linear-gradient( rgba(245, 80, 65, 1), rgba(245, 80, 65, 1) 50%, rgba(194, 48, 39, 1) 50%, rgba(194, 48, 39, 1) 100% ); &:hover { filter: brightness(1.2); } &:active { filter: brightness(0.8); } } } .nitro-card-tabs { background-color: #185D79; } .content-area { background-color: #DFDFDF; } } } .content-area { height: 100%; padding-top: 8px; padding-bottom: 8px; overflow: auto; &.theme-dark { background-color: #1C323F !important; } } @include media-breakpoint-down(lg) { .content-area { height: 100% !important; min-height: auto !important; max-height: 100% !important; } } .nitro-card-header { position: relative; height: 100%; } .nitro-card-tabs { height: 100%; min-height: 133px; max-height: 133px; border-bottom: 1px solid #283F5D; } .nitro-card-accordion-set { &.active { height: 100%; overflow: hidden; background: rgba(#FFF, 0.5); border-bottom: 1px solid rgba(#000, 0.2); } .nitro-card-accordion-set-header { border-bottom: 1px solid rgba(#000, 0.2); } }