mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Added static reply box for ActivityPub content
ref https://linear.app/tryghost/issue/AP-307/component-for-replying-to-objects-in-the-inboxfeed
This commit is contained in:
parent
1680817da2
commit
6708787731
3 changed files with 95 additions and 0 deletions
|
@ -39,6 +39,7 @@
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/react": "18.3.3",
|
"@types/react": "18.3.3",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/react-dom": "18.3.0",
|
||||||
|
"@radix-ui/react-form": "0.0.3",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {useBrowseSite} from '@tryghost/admin-x-framework/api/site';
|
||||||
import FeedItem from './FeedItem';
|
import FeedItem from './FeedItem';
|
||||||
import MainHeader from '../navigation/MainHeader';
|
import MainHeader from '../navigation/MainHeader';
|
||||||
|
|
||||||
|
import APReplyBox from '../global/APReplyBox';
|
||||||
import articleBodyStyles from '../articleBodyStyles';
|
import articleBodyStyles from '../articleBodyStyles';
|
||||||
import {type Activity} from '../activities/ActivityItem';
|
import {type Activity} from '../activities/ActivityItem';
|
||||||
|
|
||||||
|
@ -151,6 +152,8 @@ const ArticleModal: React.FC<ArticleModalProps> = ({object, actor, comments, all
|
||||||
object={object}
|
object={object}
|
||||||
type='Note'
|
type='Note'
|
||||||
/>
|
/>
|
||||||
|
<APReplyBox placeholder='Reply to @fake@user...'/>
|
||||||
|
|
||||||
{/* {object.content && <div dangerouslySetInnerHTML={({__html: object.content})} className='ap-note-content text-pretty text-[1.5rem] text-grey-900'></div>} */}
|
{/* {object.content && <div dangerouslySetInnerHTML={({__html: object.content})} className='ap-note-content text-pretty text-[1.5rem] text-grey-900'></div>} */}
|
||||||
{/* {renderAttachment(object)} */}
|
{/* {renderAttachment(object)} */}
|
||||||
{/* <FeedItem actor={actor} last={false} layout='reply' object={object} type='Note'/>
|
{/* <FeedItem actor={actor} last={false} layout='reply' object={object} type='Note'/>
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, {HTMLProps, useId} from 'react';
|
||||||
|
|
||||||
|
import * as FormPrimitive from '@radix-ui/react-form';
|
||||||
|
import APAvatar from './APAvatar';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import {Button} from '@tryghost/admin-x-design-system';
|
||||||
|
// import {useFocusContext} from '@tryghost/admin-x-design-system/types/providers/DesignSystemProvider';
|
||||||
|
|
||||||
|
export interface APTextAreaProps extends HTMLProps<HTMLTextAreaElement> {
|
||||||
|
inputRef?: React.RefObject<HTMLTextAreaElement>;
|
||||||
|
title?: string;
|
||||||
|
value?: string;
|
||||||
|
rows?: number;
|
||||||
|
error?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
hint?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const APReplyBox: React.FC<APTextAreaProps> = ({
|
||||||
|
inputRef,
|
||||||
|
title,
|
||||||
|
value,
|
||||||
|
rows = 1,
|
||||||
|
maxLength,
|
||||||
|
error,
|
||||||
|
placeholder,
|
||||||
|
hint,
|
||||||
|
className,
|
||||||
|
// onChange,
|
||||||
|
// onFocus,
|
||||||
|
// onBlur,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const id = useId();
|
||||||
|
// const {setFocusState} = useFocusContext();
|
||||||
|
|
||||||
|
// const handleFocus: FocusEventHandler<HTMLTextAreaElement> = (e) => {
|
||||||
|
// setFocusState(true);
|
||||||
|
// onFocus?.(e);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const handleBlur: FocusEventHandler<HTMLTextAreaElement> = (e) => {
|
||||||
|
// setFocusState(false);
|
||||||
|
// onBlur?.(e);
|
||||||
|
// };
|
||||||
|
|
||||||
|
const styles = clsx(
|
||||||
|
'order-2 w-full resize-none rounded-lg border bg-grey-150 px-3 py-2 text-[1.5rem] transition-all dark:bg-grey-900 dark:text-white',
|
||||||
|
error ? 'border-red bg-white' : 'border-transparent placeholder:text-grey-500 hover:bg-grey-100 focus:border-green focus:bg-white focus:shadow-[0_0_0_2px_rgba(48,207,67,0.25)] dark:placeholder:text-grey-800 dark:hover:bg-grey-925 dark:focus:bg-grey-950',
|
||||||
|
title && 'mt-1.5',
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex w-full gap-x-3 py-6'>
|
||||||
|
<APAvatar/>
|
||||||
|
<div className='relative w-full'>
|
||||||
|
<FormPrimitive.Root asChild>
|
||||||
|
<div className='flex w-full flex-col'>
|
||||||
|
<FormPrimitive.Field name={id} asChild>
|
||||||
|
<FormPrimitive.Control asChild>
|
||||||
|
<textarea
|
||||||
|
ref={inputRef}
|
||||||
|
className={styles}
|
||||||
|
id={id}
|
||||||
|
maxLength={maxLength}
|
||||||
|
placeholder={placeholder}
|
||||||
|
rows={rows}
|
||||||
|
value={value}
|
||||||
|
// onBlur={handleBlur}
|
||||||
|
// onChange={onChange}
|
||||||
|
// onFocus={handleFocus}
|
||||||
|
{...props}>
|
||||||
|
</textarea>
|
||||||
|
</FormPrimitive.Control>
|
||||||
|
</FormPrimitive.Field>
|
||||||
|
{title}
|
||||||
|
{hint}
|
||||||
|
</div>
|
||||||
|
</FormPrimitive.Root>
|
||||||
|
<div className='absolute bottom-[6px] right-[9px] flex space-x-4 transition-[opacity] duration-150'>
|
||||||
|
<Button color='black' id='post' label='Post' size='sm' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default APReplyBox;
|
Loading…
Add table
Reference in a new issue