Skip to content
Snippets Groups Projects
Radio.tsx 2.32 KiB
Newer Older
insert's avatar
insert committed
import { Children } from "../../types/Preact";
insert's avatar
insert committed
import styled, { css } from "styled-components";
insert's avatar
insert committed
import { CircleFill } from "@styled-icons/bootstrap";

interface Props {
    children: Children;
    description?: Children;
insert's avatar
insert committed

insert's avatar
insert committed
    checked: boolean;
    disabled?: boolean;
    onSelect: () => void;
}

interface BaseProps {
insert's avatar
insert committed
    selected: boolean;
insert's avatar
insert committed
}

const RadioBase = styled.label<BaseProps>`
    gap: 4px;
    z-index: 1;
    padding: 4px;
    display: flex;
    cursor: pointer;
    align-items: center;
insert's avatar
insert committed

insert's avatar
insert committed
    font-size: 1rem;
    font-weight: 600;
    user-select: none;
    border-radius: 4px;
insert's avatar
insert committed
    transition: 0.2s ease all;
insert's avatar
insert committed

    &:hover {
        background: var(--hover);
    }

    > input {
        display: none;
    }

    > div {
        margin: 4px;
        width: 24px;
        height: 24px;
        display: grid;
        border-radius: 50%;
        place-items: center;
        background: var(--foreground);

        svg {
            color: var(--foreground);
            stroke-width: 2;
        }
    }

insert's avatar
insert committed
    ${(props) =>
        props.selected &&
        css`
            color: white;
            cursor: default;
            background: var(--accent);
insert's avatar
insert committed
            > div {
                background: white;
            }
insert's avatar
insert committed
            > div svg {
                color: var(--accent);
            }
insert's avatar
insert committed
            &:hover {
                background: var(--accent);
            }
        `}
insert's avatar
insert committed
`;

const RadioDescription = styled.span<BaseProps>`
    font-size: 0.8em;
    font-weight: 400;
    color: var(--secondary-foreground);

insert's avatar
insert committed
    ${(props) =>
        props.selected &&
        css`
            color: white;
        `}
export default function Radio(props: Props) {
insert's avatar
insert committed
    return (
        <RadioBase
            selected={props.checked}
            disabled={props.disabled}
insert's avatar
insert committed
            onClick={() =>
                !props.disabled && props.onSelect && props.onSelect()
            }
insert's avatar
insert committed
        >
            <div>
                <CircleFill size={12} />
            </div>
insert's avatar
insert committed
            <input type="radio" checked={props.checked} />
insert's avatar
insert committed
            <span>
                <span>{props.children}</span>
                {props.description && (
                    <RadioDescription selected={props.checked}>
                        {props.description}
                    </RadioDescription>
                )}
            </span>
        </RadioBase>
    );
insert's avatar
insert committed
}