Skip to content

Instantly share code, notes, and snippets.

@yuheiy
Last active March 15, 2026 12:20
Show Gist options
  • Select an option

  • Save yuheiy/4f271d74fcfb5bd956ead3cdcb0ba340 to your computer and use it in GitHub Desktop.

Select an option

Save yuheiy/4f271d74fcfb5bd956ead3cdcb0ba340 to your computer and use it in GitHub Desktop.
Unavailable ActionButton in s2
import { useId, useState } from 'react';
import {
ActionButton,
Content,
ContextualHelpPopover,
DialogTrigger,
Heading,
Switch,
Text,
} from '@react-spectrum/s2';
import InfoCircleIcon from '@react-spectrum/s2/icons/InfoCircle';
import { style } from '@react-spectrum/s2/style' with { type: 'macro' };
export function App() {
let labelId = useId();
let infoIconId = useId();
let [isOpen, setOpen] = useState(false);
let [isUnavailable, setUnavailable] = useState(true);
return (
<div
className={style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
minHeight: 'screen',
rowGap: 24,
})}
>
<DialogTrigger isOpen={isOpen} onOpenChange={isUnavailable ? setOpen : undefined}>
<ActionButton
aria-labelledby={labelId}
aria-describedby={isUnavailable ? infoIconId : undefined}
onPress={isUnavailable ? undefined : () => alert('Triggering Delete')}
>
{isUnavailable && (
<InfoCircleIcon id={infoIconId} aria-label="Unavailable, expand for details" />
)}
<Text id={labelId}>Delete</Text>
</ActionButton>
{isUnavailable && (
<ContextualHelpPopover placement="bottom start" containerPadding={8} offset={8}>
<Heading slot="title">Permission required</Heading>
<Content>Contact your administrator for permissions to delete.</Content>
</ContextualHelpPopover>
)}
</DialogTrigger>
<Switch isSelected={isUnavailable} onChange={setUnavailable}>
isUnavailable
</Switch>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment