5180 fichiers 38.5 Mo 0 téléchargements 366 vues mis à jour il y a 7 heures ui
nitro-v36-with-renderer-v36 / src / components / housekeeping / views / shell / HousekeepingSidebar.tsx
HousekeepingSidebar.tsx 3.4 Ko Télécharger le fichier
import { FC, ReactNode } from 'react';
import { HousekeepingTabId, LocalizeText } from '../../../../api';
import { HousekeepingGlobalSearch } from './HousekeepingGlobalSearch';
import { BaseButton } from '../../../../common/BaseButton';
import { NativeTextTree } from '../../../../common/native-text/NativeTextTree';

export interface HousekeepingNavItem {
    id: HousekeepingTabId;
    icon: string;
    labelKey: string;
    /** Number shown on the right, e.g. users selected for a bulk action. */
    count?: number;
}

export interface HousekeepingNavGroup {
    titleKey: string;
    items: HousekeepingNavItem[];
}

/**
 * The hotel icons are pixel art in their own sizes (13x23 up to 44x38). Any
 * scaling blurs them, so each one keeps its size, centred in a slot as wide as
 * the widest: the labels start at the same x and every row has the same height.
 */
const HousekeepingNavIcon: FC<{ icon: string }> = ({ icon }) => (
    <NativeTextTree>
        <span className="flex h-[38px] w-[44px] shrink-0 items-center justify-center">
            <span className={`octane-icon octane-icon-hk-tab ${icon} shrink-0`} />
        </span>
    </NativeTextTree>
);

/** Left column of the panel: the global search over grouped sections. */
export const HousekeepingSidebar: FC<{
    groups: HousekeepingNavGroup[];
    active: HousekeepingTabId;
    onSelect: (id: HousekeepingTabId) => void;
    footer?: ReactNode;
}> = ({ groups, active, onSelect, footer }) => (
    <nav aria-label={LocalizeText('housekeeping.title')} className="flex w-[172px] shrink-0 flex-col gap-2 border-r border-zinc-300 bg-zinc-100/80 p-2">
        <HousekeepingGlobalSearch />
        <div className="flex grow flex-col gap-2 overflow-y-auto">
            {groups
                .filter((group) => group.items.length > 0)
                .map((group) => (
                    <div key={group.titleKey} className="flex flex-col gap-0.5">
                        <div className="px-1.5 text-[11px] font-bold text-[#666666]">{LocalizeText(group.titleKey)}</div>
                        {group.items.map((item) => {
                            const isActive = item.id === active;

                            return (
                                <BaseButton
                                    key={item.id}
                                    aria-current={isActive ? 'page' : undefined}
                                    className={`flex items-center gap-1.5 rounded px-1 py-0.5 text-left text-xs transition-colors ${
                                        isActive ? 'bg-white font-semibold text-zinc-900 shadow-sm ring-1 ring-zinc-300' : 'text-zinc-700 hover:bg-white/70'
                                    }`}
                                    type="button"
                                    onClick={() => onSelect(item.id)}
                                >
                                    <HousekeepingNavIcon icon={item.icon} />
                                    <span className="grow truncate">{LocalizeText(item.labelKey)}</span>
                                    {!!item.count && (
                                        <span className="rounded-full bg-sky-600 px-1.5 text-[9px] font-bold tabular-nums text-white">{item.count}</span>
                                    )}
                                </BaseButton>
                            );
                        })}
                    </div>
                ))}
        </div>
        {footer}
    </nav>
);
15Sujets
1Dépôts
20Membres
3En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser