diff --git a/app/javascript/mastodon/components/button/redesign.module.scss b/app/javascript/mastodon/components/button/redesign.module.scss index 857fca0f6a1..186fb0b6be2 100644 --- a/app/javascript/mastodon/components/button/redesign.module.scss +++ b/app/javascript/mastodon/components/button/redesign.module.scss @@ -200,3 +200,21 @@ a.base { .loading { color: inherit; } + +// Toggle tonal buttons by default show the neutral color, but when pressed show the brand color. +.toggle { + &.tonal { + @include active { + --bg: rgb(from var(--color-bg-brand-base) r g b / 10%); + --fg: var(--color-text-brand); + } + } + + &.solid, + &.ghost { + @include active { + --bg: var(--color-bg-brand-base); + --fg: var(--color-text-on-brand-base); + } + } +} diff --git a/app/javascript/mastodon/components/button/redesign.stories.tsx b/app/javascript/mastodon/components/button/redesign.stories.tsx index 1175b759d41..f2b4ef3d8ce 100644 --- a/app/javascript/mastodon/components/button/redesign.stories.tsx +++ b/app/javascript/mastodon/components/button/redesign.stories.tsx @@ -1,11 +1,12 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { fn } from 'storybook/test'; +import { useToggle } from '@/mastodon/hooks/useToggle'; import ChatIcon from '@/material-icons/400-24px/chat.svg?react'; import DownloadIcon from '@/material-icons/400-24px/download.svg?react'; import HeadphonesIcon from '@/material-icons/400-24px/headphones.svg?react'; -import { Button, IconButton } from './redesign'; +import { Button, IconButton, ToggleButton } from './redesign'; const iconArgType = { control: 'select', @@ -98,3 +99,10 @@ export const Link: Story = { as: 'link', }, }; + +export const Toggle: Story = { + render(args) { + const [active, { onToggle }] = useToggle(); + return ; + }, +}; diff --git a/app/javascript/mastodon/components/button/redesign.tsx b/app/javascript/mastodon/components/button/redesign.tsx index d9fc4caec69..3543da046ba 100644 --- a/app/javascript/mastodon/components/button/redesign.tsx +++ b/app/javascript/mastodon/components/button/redesign.tsx @@ -32,9 +32,9 @@ type ButtonAnchorProps = { as: 'a' } & ButtonPropsBase<'a'> & type ButtonLinkProps = { as: 'link' } & ButtonPropsBase<'a'> & Omit; -type ButtonProps = ButtonButtonProps | ButtonAnchorProps | ButtonLinkProps; +type BaseButtonProps = ButtonButtonProps | ButtonAnchorProps | ButtonLinkProps; -const BaseButton: React.FC = ({ +const BaseButton: React.FC = ({ size = 'md', variant = 'tonal', color = 'neutral', @@ -91,12 +91,17 @@ const BaseButton: React.FC = ({ ); }; -export const Button: React.FC< - ButtonProps & { - leadingIcon?: IconProp; - trailingIcon?: IconProp; - } -> = ({ children, leadingIcon, trailingIcon, ...props }) => ( +type ButtonProps = BaseButtonProps & { + leadingIcon?: IconProp; + trailingIcon?: IconProp; +}; + +export const Button: React.FC = ({ + children, + leadingIcon, + trailingIcon, + ...props +}) => ( {leadingIcon && !props.loading && ( @@ -109,7 +114,7 @@ export const Button: React.FC< ); -export const IconButton: React.FC = ({ +export const IconButton: React.FC = ({ icon, className, children, @@ -133,3 +138,17 @@ const LoadingIcon: React.FC = () => ( role='none' /> ); + +export const ToggleButton: React.FC = ({ + active, + className, + ...props +}) => ( +