fix(message): give the action rail custom stroke icons, drop its inline reactions, and lift it above the bubble
This commit is contained in:
parent
78f9b84850
commit
ebc7ec87f0
2 changed files with 72 additions and 53 deletions
|
|
@ -116,45 +116,69 @@ export const MessageQuickReactions = as<'div', MessageQuickReactionsProps>(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default reactions shown in the hover rail before a user has built up any
|
// Hover action-rail icons — thin stroke-outline style matching the composer's
|
||||||
// recent-emoji history, so the "быстрый рельс" always offers one-tap reactions.
|
// StreamComposerIcons (Dawn canon), replacing folds' stock filled glyphs so the
|
||||||
const RAIL_DEFAULT_REACTIONS: { unicode: string; shortcode: string }[] = [
|
// rail reads distinct from upstream Cinny. folds Icon wraps these in
|
||||||
{ unicode: '👍', shortcode: 'thumbsup' },
|
// `<svg viewBox="0 0 24 24" fill="none">`, so each returns just the shapes.
|
||||||
{ unicode: '❤️', shortcode: 'heart' },
|
const RailIcons = {
|
||||||
{ unicode: '😂', shortcode: 'joy' },
|
Smile: () => (
|
||||||
];
|
|
||||||
|
|
||||||
type RailQuickReactionsProps = {
|
|
||||||
onReaction: (key: string, shortcode?: string) => void;
|
|
||||||
};
|
|
||||||
// Inline quick-reactions surfaced directly in the hover action rail — react in
|
|
||||||
// one tap without opening the emoji board. Mounts ONLY inside the
|
|
||||||
// conditionally-rendered rail (one row at a time), so there is no per-row cost.
|
|
||||||
function RailQuickReactions({ onReaction }: RailQuickReactionsProps) {
|
|
||||||
const mx = useMatrixClient();
|
|
||||||
const recent = useRecentEmoji(mx, 3);
|
|
||||||
const items =
|
|
||||||
recent.length > 0
|
|
||||||
? recent.slice(0, 3).map((e) => ({ unicode: e.unicode, shortcode: e.shortcode }))
|
|
||||||
: RAIL_DEFAULT_REACTIONS;
|
|
||||||
return (
|
|
||||||
<>
|
<>
|
||||||
{items.map((emoji) => (
|
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.6" />
|
||||||
<IconButton
|
<path
|
||||||
key={emoji.unicode}
|
d="M8 14s1.5 2 4 2 4-2 4-2M9 10h.01M15 10h.01"
|
||||||
size="300"
|
stroke="currentColor"
|
||||||
variant="SurfaceVariant"
|
strokeWidth="1.6"
|
||||||
radii="300"
|
strokeLinecap="round"
|
||||||
title={emoji.shortcode}
|
/>
|
||||||
aria-label={emoji.shortcode}
|
|
||||||
onClick={() => onReaction(emoji.unicode, emoji.shortcode)}
|
|
||||||
>
|
|
||||||
<Text size="T400">{emoji.unicode}</Text>
|
|
||||||
</IconButton>
|
|
||||||
))}
|
|
||||||
</>
|
</>
|
||||||
);
|
),
|
||||||
}
|
Reply: () => (
|
||||||
|
<>
|
||||||
|
<path
|
||||||
|
d="M9 17L4 12l5-5"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.7"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M20 18v-2a4 4 0 0 0-4-4H4"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.7"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
Thread: () => (
|
||||||
|
<>
|
||||||
|
<path
|
||||||
|
d="M5 4h14a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H8l-4 4V5a1 1 0 0 1 1-1z"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.7"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
<path d="M12 7.5v4M10 9.5h4" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
Edit: () => (
|
||||||
|
<path
|
||||||
|
d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1.7"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
More: () => (
|
||||||
|
<path
|
||||||
|
d="M5 12h.01M12 12h.01M19 12h.01"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2.6"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
export const MessageAllReactionItem = as<
|
export const MessageAllReactionItem = as<
|
||||||
'button',
|
'button',
|
||||||
|
|
@ -954,14 +978,6 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
<div className={css.MessageOptionsBase}>
|
<div className={css.MessageOptionsBase}>
|
||||||
<Menu className={css.MessageOptionsBar} variant="SurfaceVariant">
|
<Menu className={css.MessageOptionsBar} variant="SurfaceVariant">
|
||||||
<Box gap="100">
|
<Box gap="100">
|
||||||
{canSendReaction && (
|
|
||||||
<RailQuickReactions
|
|
||||||
onReaction={(key, shortcode) => {
|
|
||||||
const evtId = mEvent.getId();
|
|
||||||
if (evtId) onReactionToggle(evtId, key, shortcode);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{canSendReaction && (
|
{canSendReaction && (
|
||||||
<PopOut
|
<PopOut
|
||||||
position="Bottom"
|
position="Bottom"
|
||||||
|
|
@ -996,7 +1012,7 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
radii="300"
|
radii="300"
|
||||||
aria-pressed={!!emojiBoardAnchor}
|
aria-pressed={!!emojiBoardAnchor}
|
||||||
>
|
>
|
||||||
<Icon src={Icons.SmilePlus} size="100" />
|
<Icon src={RailIcons.Smile} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</PopOut>
|
</PopOut>
|
||||||
)}
|
)}
|
||||||
|
|
@ -1008,7 +1024,7 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
size="300"
|
size="300"
|
||||||
radii="300"
|
radii="300"
|
||||||
>
|
>
|
||||||
<Icon src={Icons.ReplyArrow} size="100" />
|
<Icon src={RailIcons.Reply} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
{!isThreadReply && !hideThreadReplyAffordance && (
|
{!isThreadReply && !hideThreadReplyAffordance && (
|
||||||
|
|
@ -1019,7 +1035,7 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
size="300"
|
size="300"
|
||||||
radii="300"
|
radii="300"
|
||||||
>
|
>
|
||||||
<Icon src={Icons.ThreadPlus} size="100" />
|
<Icon src={RailIcons.Thread} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
{canEditEvent(mx, mEvent) && onEditId && (
|
{canEditEvent(mx, mEvent) && onEditId && (
|
||||||
|
|
@ -1029,7 +1045,7 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
size="300"
|
size="300"
|
||||||
radii="300"
|
radii="300"
|
||||||
>
|
>
|
||||||
<Icon src={Icons.Pencil} size="100" />
|
<Icon src={RailIcons.Edit} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
)}
|
)}
|
||||||
<PopOut
|
<PopOut
|
||||||
|
|
@ -1198,7 +1214,7 @@ const MessageInner = as<'div', MessageProps>(
|
||||||
onClick={handleOpenMenu}
|
onClick={handleOpenMenu}
|
||||||
aria-pressed={!!menuAnchor}
|
aria-pressed={!!menuAnchor}
|
||||||
>
|
>
|
||||||
<Icon src={Icons.VerticalDots} size="100" />
|
<Icon src={RailIcons.More} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</PopOut>
|
</PopOut>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1540,7 +1556,7 @@ export const Event = as<'div', EventProps>(
|
||||||
onClick={handleOpenMenu}
|
onClick={handleOpenMenu}
|
||||||
aria-pressed={!!menuAnchor}
|
aria-pressed={!!menuAnchor}
|
||||||
>
|
>
|
||||||
<Icon src={Icons.VerticalDots} size="100" />
|
<Icon src={RailIcons.More} size="100" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</PopOut>
|
</PopOut>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@ export const MessageOptionsBase = style([
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
// Hug the message's top-right corner with a small overlap instead of the old
|
// Hug the message's top-right corner with a small overlap instead of the old
|
||||||
// -30px overhang that detached the rail from the row and clipped at the
|
// -30px overhang that detached the rail from the row and clipped at the
|
||||||
// timeline top. (First iteration — exact offset is easy to nudge.)
|
// timeline top. (Exact offset is easy to nudge.)
|
||||||
top: toRem(-14),
|
top: toRem(-14),
|
||||||
right: config.space.S200,
|
right: config.space.S200,
|
||||||
zIndex: 1,
|
// Above the message content/bubble (which sits at zIndex 2 in layout.css.ts)
|
||||||
|
// so the rail never renders behind the bubble — was the "за баблом" bug on
|
||||||
|
// native where the rail overlaps the bubble's top-right.
|
||||||
|
zIndex: 5,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
export const MessageOptionsBar = style([
|
export const MessageOptionsBar = style([
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue