mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
90 lines
2.0 KiB
TypeScript
90 lines
2.0 KiB
TypeScript
import styled from '@emotion/styled';
|
|
|
|
import Radio from 'sentry/components/radio';
|
|
import {space} from 'sentry/styles/space';
|
|
|
|
type RadioPanelGroupProps<C extends string> = {
|
|
/**
|
|
* An array of [id, name]
|
|
*/
|
|
choices: [C, React.ReactNode, React.ReactNode?][];
|
|
label: string;
|
|
onChange: (id: C, e: React.FormEvent<HTMLInputElement>) => void;
|
|
value: string | null;
|
|
};
|
|
|
|
type Props<C extends string> = RadioPanelGroupProps<C> &
|
|
Omit<React.HTMLAttributes<HTMLDivElement>, keyof RadioPanelGroupProps<C>>;
|
|
|
|
function RadioPanelGroup<C extends string>({
|
|
value,
|
|
choices,
|
|
label,
|
|
onChange,
|
|
...props
|
|
}: Props<C>) {
|
|
return (
|
|
<Container {...props} role="radiogroup" aria-labelledby={label}>
|
|
{(choices || []).map(([id, name, extraContent], index) => (
|
|
<RadioPanel key={index}>
|
|
<RadioLineItem role="radio" index={index} aria-checked={value === id}>
|
|
<Radio
|
|
radioSize="small"
|
|
aria-label={id}
|
|
checked={value === id}
|
|
onChange={(e: React.FormEvent<HTMLInputElement>) => onChange(id, e)}
|
|
/>
|
|
<div>{name}</div>
|
|
{extraContent}
|
|
</RadioLineItem>
|
|
</RadioPanel>
|
|
))}
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
export default RadioPanelGroup;
|
|
|
|
const Container = styled('div')`
|
|
display: grid;
|
|
gap: ${space(1)};
|
|
grid-auto-flow: row;
|
|
grid-auto-rows: max-content;
|
|
grid-auto-columns: auto;
|
|
`;
|
|
|
|
const RadioLineItem = styled('label')<{
|
|
index: number;
|
|
}>`
|
|
display: grid;
|
|
gap: ${space(0.25)} ${space(1)};
|
|
grid-template-columns: max-content auto max-content;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
outline: none;
|
|
font-weight: normal;
|
|
margin: 0;
|
|
color: ${p => p.theme.subText};
|
|
transition: color 0.3s ease-in;
|
|
padding: 0;
|
|
position: relative;
|
|
|
|
&:hover,
|
|
&:focus {
|
|
color: ${p => p.theme.textColor};
|
|
}
|
|
|
|
svg {
|
|
display: none;
|
|
opacity: 0;
|
|
}
|
|
|
|
&[aria-checked='true'] {
|
|
color: ${p => p.theme.textColor};
|
|
}
|
|
`;
|
|
|
|
const RadioPanel = styled('div')`
|
|
margin: 0;
|
|
`;
|