diff --git a/web/src/pages/creator/messages/index.tsx b/web/src/pages/creator/messages/index.tsx
index 9e21b4f..d6bda5f 100644
--- a/web/src/pages/creator/messages/index.tsx
+++ b/web/src/pages/creator/messages/index.tsx
@@ -331,6 +331,7 @@ export default function PrivateMessagesPage() {
,
}))}
activeKey={activeKey} onActiveChange={setActiveKey}
+ styles={{ item: { height: 'auto', paddingBlock: 8, flexShrink: 0 } }}
style={{ width: '100%', flex: 1, overflowY: 'auto' }}
/> : }
{visibleContacts.length < contactTotal && }
diff --git a/web/tests/private-messages-page.test.cjs b/web/tests/private-messages-page.test.cjs
index c00b185..2516e05 100644
--- a/web/tests/private-messages-page.test.cjs
+++ b/web/tests/private-messages-page.test.cjs
@@ -210,6 +210,29 @@ test('same peer on different accounts has distinct stable keys, source names and
assert.equal(query.get('account_id'), 'b'); assert.equal(query.get('peer_uid'), '100');
});
+test('three-line conversation items grow with content, keep vertical padding and never shrink in a long list', async (t) => {
+ const rows = Array.from({ length: 50 }, (_, index) => ({
+ ...contacts[0], peer_uid: String(100 + index),
+ peer_name: '较长的联系人名称'.repeat(10), last_text: '较长的消息摘要'.repeat(20),
+ }));
+ const h = harness({ contacts: rows }); t.after(h.dispose);
+ const tree = await h.flush();
+ const props = conversations(h, tree).props;
+ assert.equal(props.styles?.item?.height, 'auto');
+ assert.equal(props.styles.item.flexShrink, 0);
+ assert.equal(props.styles.item.paddingBlock, 8);
+ assert.equal(props.style.overflowY, 'auto');
+ assert.equal(props.items.length, rows.length);
+ for (const item of props.items) {
+ assert.equal(item.label.props.vertical, true);
+ const lines = React.Children.toArray(item.label.props.children);
+ assert.equal(lines.length, 3);
+ assert.ok(lines.every((line) => line.props.ellipsis.tooltip));
+ }
+ const selected = await choose(h, 'a:149');
+ assert.equal(conversations(h, selected).props.activeKey, 'a:149');
+});
+
test('messages are chronological, received left/sent right, with real times, errors and non-text placeholders', async (t) => {
const h = harness({ messages: { data: [
record(4, { message_type: 'image', text: 'not rendered as image' }),