wuespace/telestion-client

View on GitHub
packages/telestion-client-common/src/components/header/account-controls/status-dialog.tsx

Summary

Maintainability
A
40 mins
Test Coverage
import { ReactNode, useMemo } from 'react';
import { StateSelector } from 'zustand';
import {
    Content,
    Dialog,
    Divider,
    Heading,
    Grid,
    Text,
    Provider
} from '@adobe/react-spectrum';
import { useStatus } from './use-status';
import { ColorScheme, ColorSchemeState, useColorScheme } from '../../../hooks';

// color scheme selector
const selector: StateSelector<ColorSchemeState, ColorScheme> = ({
    colorScheme
}) => colorScheme;

/**
 * Renders a status dialog containing the current application state
 * (for example, the event bus connection status and the logged in username).
 *
 * The entries are defined in the {@link useStatus} hook.
 *
 * This component contains a {@link @adobe/react-spectrum#Dialog}
 * which can be controlled using a {@link @adobe/react-spectrum#DialogContainer}.
 *
 * Typically, it opens when the status button in the {@link AvatarMenu} gets clicked.
 *
 * @see {@link useStatus}
 *
 * @example
 * ```ts
 * function MyAccountControls() {
 *     // dialog open state
 *     const [isOpen, setOpen] = useState(false);
 *
 *     const openDialog = useCallback(() => setOpen(true), []);
 *     const closeDialog = useCallback(() => setOpen(false), []);
 *
 *     return (
 *         <>
 *             <MenuTrigger>
 *                 <AvatarButton />
 *                 <AvatarMenu onStatusClick={openDialog} />
 *             </MenuTrigger>
 *
 *             <DialogContainer type="modal" isDismissable onDismiss={closeDialog}>
 *                 {isOpen && <StatusDialog />}
 *             </DialogContainer>
 *         </>
 *     );
 * }
 * ```
 */
export function StatusDialog() {
    const colorScheme = useColorScheme(selector);
    const status = useStatus();

    const items = useMemo(() => {
        const children: Array<ReactNode> = [];

        status.forEach(({ description, state }) => {
            children.push(
                <Text key={`${description}-description`}>{description}</Text>
            );
            children.push(<Text key={`${description}-state`}>{state}</Text>);
        });

        return children;
    }, [status]);

    return (
        <Provider colorScheme={colorScheme !== 'system' ? colorScheme : undefined}>
            <Dialog data-testid="telestionClientStatusDialog">
                <Heading data-testid="telestionClientStatusDialog-heading">
                    Status
                </Heading>
                <Divider />
                <Content>
                    <Grid
                        columns="max-content auto"
                        columnGap="size-200"
                        rowGap="size-100"
                        data-testid="telestionClientStatusDialog-content"
                    >
                        {items}
                    </Grid>
                </Content>
            </Dialog>
        </Provider>
    );
}