Add share dialog for collections (#37986)
This commit is contained in:
1 parent
bca57020a0
commit
7970eb392a
17 files changed
+498
-72
No files matched your search
@@ -7,6 +7,8 @@ import { useHovering } from 'mastodon/hooks/useHovering';
|
||||
import { autoPlayGif } from 'mastodon/initial_state';
|
||||
import type { Account } from 'mastodon/models/account';
|
||||
|
||||
import { useAccount } from '../hooks/useAccount';
|
||||
|
||||
interface Props {
|
||||
account:
|
||||
| Pick<Account, 'id' | 'acct' | 'avatar' | 'avatar_static'>
|
||||
@@ -91,3 +93,10 @@ export const Avatar: React.FC<Props> = ({
|
||||
|
||||
return avatar;
|
||||
};
|
||||
|
||||
export const AvatarById: React.FC<
|
||||
{ accountId: string } & Omit<Props, 'account'>
|
||||
> = ({ accountId, ...otherProps }) => {
|
||||
const account = useAccount(accountId);
|
||||
return <Avatar account={account} {...otherProps} />;
|
||||
};
|
||||
@@ -19,8 +19,9 @@ const messages = defineMessages({
|
||||
export const CopyIconButton: React.FC<{
|
||||
title: string;
|
||||
value: string;
|
||||
className: string;
|
||||
}> = ({ title, value, className }) => {
|
||||
className?: string;
|
||||
'aria-describedby'?: string;
|
||||
}> = ({ title, value, className, 'aria-describedby': ariaDescribedBy }) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -38,8 +39,9 @@ export const CopyIconButton: React.FC<{
|
||||
className={classNames(className, copied ? 'copied' : 'copyable')}
|
||||
title={title}
|
||||
onClick={handleClick}
|
||||
icon=''
|
||||
icon='copy-icon'
|
||||
iconComponent={ContentCopyIcon}
|
||||
aria-describedby={ariaDescribedBy}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
.wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input {
|
||||
padding-inline-end: 45px;
|
||||
}
|
||||
|
||||
.copyButton {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
padding: 9px;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { forwardRef, useCallback, useRef } from 'react';
|
||||
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CopyIconButton } from 'mastodon/components/copy_icon_button';
|
||||
|
||||
import classes from './copy_link_field.module.scss';
|
||||
import { FormFieldWrapper } from './form_field_wrapper';
|
||||
import type { CommonFieldWrapperProps } from './form_field_wrapper';
|
||||
import { TextInput } from './text_input_field';
|
||||
import type { TextInputProps } from './text_input_field';
|
||||
|
||||
interface CopyLinkFieldProps extends CommonFieldWrapperProps, TextInputProps {
|
||||
value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A read-only text field with a button for copying the field value
|
||||
*/
|
||||
|
||||
export const CopyLinkField = forwardRef<HTMLInputElement, CopyLinkFieldProps>(
|
||||
(
|
||||
{ id, label, hint, hasError, value, required, className, ...otherProps },
|
||||
ref,
|
||||
) => {
|
||||
const intl = useIntl();
|
||||
const inputRef = useRef<HTMLInputElement | null>();
|
||||
const handleFocus = useCallback(() => {
|
||||
inputRef.current?.select();
|
||||
}, []);
|
||||
|
||||
const mergeRefs = useCallback(
|
||||
(element: HTMLInputElement | null) => {
|
||||
inputRef.current = element;
|
||||
if (typeof ref === 'function') {
|
||||
ref(element);
|
||||
} else if (ref) {
|
||||
ref.current = element;
|
||||
}
|
||||
},
|
||||
[ref],
|
||||
);
|
||||
|
||||
return (
|
||||
<FormFieldWrapper
|
||||
label={label}
|
||||
hint={hint}
|
||||
required={required}
|
||||
hasError={hasError}
|
||||
inputId={id}
|
||||
>
|
||||
{(inputProps) => (
|
||||
<div className={classes.wrapper}>
|
||||
<TextInput
|
||||
readOnly
|
||||
{...otherProps}
|
||||
{...inputProps}
|
||||
ref={mergeRefs}
|
||||
value={value}
|
||||
onFocus={handleFocus}
|
||||
className={classNames(className, classes.input)}
|
||||
/>
|
||||
<CopyIconButton
|
||||
value={value}
|
||||
title={intl.formatMessage({
|
||||
id: 'copy_icon_button.copy_this_text',
|
||||
defaultMessage: 'Copy link to clipboard',
|
||||
})}
|
||||
className={classes.copyButton}
|
||||
aria-describedby={inputProps.id}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</FormFieldWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
CopyLinkField.displayName = 'CopyLinkField';
|
||||
@@ -1,3 +1,4 @@
|
||||
export { FormFieldWrapper } from './form_field_wrapper';
|
||||
export { FormStack } from './form_stack';
|
||||
export { Fieldset } from './fieldset';
|
||||
export { TextInputField, TextInput } from './text_input_field';
|
||||
@@ -8,6 +9,7 @@ export {
|
||||
Combobox,
|
||||
type ComboboxItemState,
|
||||
} from './combobox_field';
|
||||
export { CopyLinkField } from './copy_link_field';
|
||||
export { RadioButtonField, RadioButton } from './radio_button_field';
|
||||
export { ToggleField, Toggle } from './toggle_field';
|
||||
export { SelectField, Select } from './select_field';
|
||||
@@ -0,0 +1,56 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface SimpleComponentProps {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface ModalShellComponent extends React.FC<SimpleComponentProps> {
|
||||
Body: React.FC<SimpleComponentProps>;
|
||||
Actions: React.FC<SimpleComponentProps>;
|
||||
}
|
||||
|
||||
export const ModalShell: ModalShellComponent = ({ children, className }) => {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'modal-root__modal',
|
||||
'safety-action-modal',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ModalShellBody: ModalShellComponent['Body'] = ({
|
||||
children,
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<div className='safety-action-modal__top'>
|
||||
<div
|
||||
className={classNames('safety-action-modal__confirmation', className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ModalShellActions: ModalShellComponent['Actions'] = ({
|
||||
children,
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<div className='safety-action-modal__bottom'>
|
||||
<div className={classNames('safety-action-modal__actions', className)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ModalShell.Body = ModalShellBody;
|
||||
ModalShell.Actions = ModalShellActions;
|
||||
Reference in new issue
Block a user