Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions packages/@react-spectrum/s2/chromatic/ActionButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {ActionButton, ActionButtonProps} from '../src/ActionButton';
import {Avatar} from '../src/Avatar';
import BellIcon from '../s2wf-icons/S2_Icon_Bell_20_N.svg';
import CommentIcon from '../s2wf-icons/S2_Icon_Comment_20_N.svg';
import Cut from '../s2wf-icons/S2_Icon_Cut_20_N.svg';
import {Fonts, NotificationBadges, UnsafeClassName} from '../stories/ActionButton.stories';
import {generatePowerset} from '@react-spectrum/story-utils';
import type {Meta, StoryObj} from '@storybook/react';
Expand Down Expand Up @@ -133,6 +134,39 @@ export const AvatarOnly: ActionButtonStory = {

export {Fonts, UnsafeClassName, NotificationBadges};

const sizes = ['XS', 'S', 'M', 'L', 'XL'] as const;

export const HoldAffordance: ActionButtonStory = {
render: () => (
<div className={style({display: 'flex', flexDirection: 'column', gap: 16})}>
{sizes.map(size => (
<div key={size} className={style({display: 'flex', gap: 8, alignItems: 'center'})}>
<ActionButton size={size} holdAffordance aria-label={`icon only ${size}`}>
<Cut />
</ActionButton>
<ActionButton size={size} holdAffordance>
<Text>Cut</Text>
</ActionButton>
<ActionButton size={size} holdAffordance>
<Cut />
<Text>Cut</Text>
</ActionButton>
<ActionButton size={size} holdAffordance isQuiet aria-label={`quiet icon only ${size}`}>
<Cut />
</ActionButton>
<ActionButton size={size} holdAffordance isQuiet>
<Text>Cut</Text>
</ActionButton>
<ActionButton size={size} holdAffordance isQuiet>
<Cut />
<Text>Cut</Text>
</ActionButton>
</div>
))}
</div>
)
};

export const NotificationBadgesCustomWidth: ActionButtonStory = {
render: args => (
<div className={style({display: 'flex', flexDirection: 'column', gap: 8})}>
Expand Down
34 changes: 34 additions & 0 deletions packages/@react-spectrum/s2/chromatic/ToggleButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
StaticColorDecorator,
StaticColorProvider
} from '../stories/utils';
import Cut from '../s2wf-icons/S2_Icon_Cut_20_N.svg';
import {generatePowerset} from '@react-spectrum/story-utils';
import type {Meta, StoryObj} from '@storybook/react';
import NewIcon from '../s2wf-icons/S2_Icon_New_20_N.svg';
Expand Down Expand Up @@ -128,3 +129,36 @@ export const Truncate: StoryObj<typeof Template> = {
</div>
)
};

const sizes = ['XS', 'S', 'M', 'L', 'XL'] as const;

export const HoldAffordance: StoryObj<typeof Template> = {
render: () => (
<div className={style({display: 'flex', flexDirection: 'column', gap: 16})}>
{sizes.map(size => (
<div key={size} className={style({display: 'flex', gap: 8, alignItems: 'center'})}>
<ToggleButton size={size} holdAffordance aria-label={`icon only ${size}`}>
<Cut />
</ToggleButton>
<ToggleButton size={size} holdAffordance>
<Text>Cut</Text>
</ToggleButton>
<ToggleButton size={size} holdAffordance>
<Cut />
<Text>Cut</Text>
</ToggleButton>
<ToggleButton size={size} holdAffordance isQuiet aria-label={`quiet icon only ${size}`}>
<Cut />
</ToggleButton>
<ToggleButton size={size} holdAffordance isQuiet>
<Text>Cut</Text>
</ToggleButton>
<ToggleButton size={size} holdAffordance isQuiet>
<Cut />
<Text>Cut</Text>
</ToggleButton>
</div>
))}
</div>
)
};
48 changes: 46 additions & 2 deletions packages/@react-spectrum/s2/src/ActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@

import {ActionButtonGroupContext} from './ActionButtonGroup';
import {AvatarContext} from './Avatar';
import {baseColor, focusRing, fontRelative, lightDark, style} from '../style' with {type: 'macro'};
import {
baseColor,
focusRing,
fontRelative,
lightDark,
space,
style
} from '../style' with {type: 'macro'};
import {ButtonProps, ButtonRenderProps, Button as RACButton} from 'react-aria-components/Button';
import {centerBaseline} from './CenterBaseline';
import {ContextValue, Provider, useSlottedContext} from 'react-aria-components/slots';
Expand All @@ -22,12 +29,13 @@ import {
staticColor,
StyleProps
} from './style-utils' with {type: 'macro'};
import CornerTriangle from '../ui-icons/CornerTriangle';
import {createContext, forwardRef, ReactNode, useContext} from 'react';
import {FocusableRef, FocusableRefValue, GlobalDOMAttributes} from '@react-types/shared';
import {IconContext} from './Icon';
import {ImageContext} from './Image';
import intlMessages from '../intl/*.json';
// @ts-ignore
import intlMessages from '../intl/*.json';
import {NotificationBadgeContext} from './NotificationBadge';
import {OverlayTriggerStateContext} from 'react-aria-components/Dialog';
import {pressScale} from './pressScale';
Expand All @@ -36,6 +44,7 @@ import {SkeletonContext} from './Skeleton';
import {Text, TextContext} from './Content';
import {useFocusableRef} from './useDOMRef';
import {useFormProps} from './Form';
import {useLocale} from 'react-aria/I18nProvider';
import {useLocalizedStringFormatter} from 'react-aria/useLocalizedStringFormatter';
import {usePendingState} from './Button';
import {useSpectrumContextProps} from './useSpectrumContextProps';
Expand All @@ -54,6 +63,8 @@ export interface ActionButtonStyleProps {
* style](https://spectrum.adobe.com/page/action-button/#Quiet).
*/
isQuiet?: boolean;
/** @private */
holdAffordance?: boolean;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just add to the context interface?

}

interface ToggleButtonStyleProps {
Expand Down Expand Up @@ -340,6 +351,8 @@ export const ActionButton = forwardRef(function ActionButton(
} = ctx || {};

let {isProgressVisible} = usePendingState(isPending);
let {holdAffordance} = props;
let {direction} = useLocale();

return (
<RACButton
Expand Down Expand Up @@ -470,6 +483,37 @@ export const ActionButton = forwardRef(function ActionButton(
</div>
)}
</Provider>
{holdAffordance && (
<CornerTriangle
size={size === 'XS' ? 'S' : size}
className={style({
position: 'absolute',
insetEnd: {
size: {
XS: space(3),
S: space(3),
M: 4,
L: space(5),
XL: space(6)
}
},
bottom: {
size: {
XS: space(3),
S: space(3),
M: 4,
L: space(5),
XL: space(6)
}
},
scaleX: {
direction: {
rtl: -1
}
}
})({direction, size})}
/>
)}
</>
)}
</RACButton>
Expand Down
52 changes: 30 additions & 22 deletions packages/@react-spectrum/s2/src/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* governing permissions and limitations under the License.
*/

import {ActionButtonContext} from './ActionButton';
import {
Menu as AriaMenu,
MenuItem as AriaMenuItem,
Expand All @@ -23,7 +24,6 @@ import {
SubmenuTriggerProps as AriaSubmenuTriggerProps,
MenuItemRenderProps
} from 'react-aria-components/Menu';

import {
baseColor,
centerPadding,
Expand Down Expand Up @@ -61,17 +61,18 @@ import {edgeToText} from '../style/spectrum-theme' with {type: 'macro'};
import {forwardRefType} from './types';
import {HeaderContext, HeadingContext, KeyboardContext, Text, TextContext} from './Content';
import {IconContext} from './Icon';
import {ImageContext} from './Image';
import InfoCircleIcon from '../s2wf-icons/S2_Icon_InfoCircle_20_N.svg'; // chevron right removed??
import {ImageContext} from './Image'; // chevron right removed??
import InfoCircleIcon from '../s2wf-icons/S2_Icon_InfoCircle_20_N.svg';
import {InPopoverContext, Popover, PopoverContext} from './Popover';
import intlMessages from '../intl/*.json';
// @ts-ignore
import intlMessages from '../intl/*.json';
import LinkOutIcon from '../ui-icons/LinkOut';
import {mergeStyles} from '../style/runtime';
import {Placement} from 'react-aria/useOverlayPosition';
import {PressResponder} from 'react-aria/private/interactions/PressResponder';
import {pressScale} from './pressScale';
import {Separator, SeparatorProps} from 'react-aria-components/Separator';
import {ToggleButtonContext} from './ToggleButton';
import {useGlobalListeners} from 'react-aria/private/utils/useGlobalListeners';
import {useId} from 'react-aria/useId';
import {useLocale} from 'react-aria/I18nProvider';
Expand Down Expand Up @@ -736,7 +737,7 @@ function MenuTrigger(props: MenuTriggerProps): ReactNode {
);
};

let {align = 'start', direction = 'bottom', shouldFlip} = props;
let {align = 'start', direction = 'bottom', shouldFlip, trigger = 'press'} = props;
let placement: Placement;
switch (direction) {
case 'left':
Expand All @@ -750,25 +751,32 @@ function MenuTrigger(props: MenuTriggerProps): ReactNode {
default:
placement = `${direction} ${align}` as Placement;
}
let holdAffordance = trigger === 'longPress';

return (
<InternalMenuTriggerContext.Provider
value={{
align: props.align,
direction: props.direction,
shouldFlip: props.shouldFlip
}}>
<PopoverContext.Provider
value={{hideArrow: true, offset: 8, crossOffset: 0, placement, shouldFlip}}>
<InPopoverContext.Provider value={false}>
<AriaMenuTrigger {...props}>
<PressResponder onPressStart={onPressStart} isPressed={isPressed}>
{props.children}
</PressResponder>
</AriaMenuTrigger>
</InPopoverContext.Provider>
</PopoverContext.Provider>
</InternalMenuTriggerContext.Provider>
<Provider
values={[
[ActionButtonContext, {holdAffordance}],
[ToggleButtonContext, {holdAffordance}]
]}>
<InternalMenuTriggerContext.Provider
value={{
align: props.align,
direction: props.direction,
shouldFlip: props.shouldFlip
}}>
<PopoverContext.Provider
value={{hideArrow: true, offset: 8, crossOffset: 0, placement, shouldFlip}}>
<InPopoverContext.Provider value={false}>
<AriaMenuTrigger {...props}>
<PressResponder onPressStart={onPressStart} isPressed={isPressed}>
{props.children}
</PressResponder>
</AriaMenuTrigger>
</InPopoverContext.Provider>
</PopoverContext.Provider>
</InternalMenuTriggerContext.Provider>
</Provider>
);
}

Expand Down
37 changes: 36 additions & 1 deletion packages/@react-spectrum/s2/src/ToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
import {ActionButtonStyleProps, btnStyles} from './ActionButton';
import {centerBaseline} from './CenterBaseline';
import {ContextValue, Provider, useSlottedContext} from 'react-aria-components/slots';
import CornerTriangle from '../ui-icons/CornerTriangle';
import {createContext, forwardRef, ReactNode} from 'react';
import {FocusableRef, FocusableRefValue, GlobalDOMAttributes} from '@react-types/shared';
import {fontRelative, style} from '../style' with {type: 'macro'};
import {fontRelative, space, style} from '../style' with {type: 'macro'};
import {IconContext} from './Icon';
import {pressScale} from './pressScale';
import {
Expand All @@ -28,6 +29,7 @@ import {Text, TextContext} from './Content';
import {ToggleButtonGroupContext} from './ToggleButtonGroup';
import {useFocusableRef} from './useDOMRef';
import {useFormProps} from './Form';
import {useLocale} from 'react-aria/I18nProvider';
import {useSpectrumContextProps} from './useSpectrumContextProps';

export interface ToggleButtonProps
Expand Down Expand Up @@ -84,6 +86,8 @@ export const ToggleButton = forwardRef(function ToggleButton(
size = props.size || 'M',
isDisabled = props.isDisabled
} = ctx || {};
let {holdAffordance} = props;
let {direction} = useLocale();

return (
<RACToggleButton
Expand Down Expand Up @@ -124,6 +128,37 @@ export const ToggleButton = forwardRef(function ToggleButton(
]}>
{typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}
</Provider>
{holdAffordance && (
<CornerTriangle
size={size === 'XS' ? 'S' : size}
className={style({
position: 'absolute',
insetEnd: {
size: {
XS: space(3),
S: space(3),
M: 4,
L: space(5),
XL: space(6)
}
},
bottom: {
size: {
XS: space(3),
S: space(3),
M: 4,
L: space(5),
XL: space(6)
}
},
scaleX: {
direction: {
rtl: -1
}
}
})({direction, size})}
/>
)}
</RACToggleButton>
);
});
Loading