Limit member label width

This commit is contained in:
Scott Nonnenberg
2026-02-06 10:08:34 +10:00
committed by GitHub
parent 834f0c7775
commit 2398edf1b7
12 changed files with 88 additions and 11 deletions

View File

@@ -1072,8 +1072,10 @@ $message-padding-horizontal: 12px;
.module-message__author { .module-message__author {
@include mixins.font-body-small-bold; @include mixins.font-body-small-bold;
min-height: 18px;
user-select: none; user-select: none;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 3px;
} }
.module-message__author_with_sticker { .module-message__author_with_sticker {

View File

@@ -72,12 +72,13 @@
@include mixins.button-focus-outline; @include mixins.button-focus-outline;
& { & {
border: 1px solid transparent;
// Note: matches the border radius in ContactName.scss, for --label-pill // Note: matches the border radius in ContactName.scss, for --label-pill
border-radius: 9px; border-radius: 9px;
margin-top: 6px; margin-top: 6px;
margin-bottom: 4px; margin-bottom: 4px;
max-width: 100%;
} }
} }

View File

@@ -286,17 +286,25 @@ $contact-colors: (
padding-block: 1px; padding-block: 1px;
border-radius: 9px; border-radius: 9px;
white-space: nowrap; white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
} }
&--label-pill--inner { &--label-pill--inner {
display: flex; display: flex;
align-items: center; align-items: center;
white-space: nowrap; white-space: nowrap;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
} }
&--label-pill--bubble { &--label-pill--bubble {
margin-top: -2px; margin-inline-start: 2px;
margin-bottom: 2px; margin-bottom: -4px;
max-width: calc(100% - 2px);
} }
&--label-pill--emoji { &--label-pill--emoji {
@@ -318,8 +326,14 @@ $contact-colors: (
} }
} }
&--label-pill--list {
margin-bottom: -5px;
}
&--label-pill--text { &--label-pill--text {
display: inline-block; display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
} }
@each $name, $value in $contact-colors { @each $name, $value in $contact-colors {

View File

@@ -45,6 +45,10 @@
} }
} }
&-membership-list--member-label {
@include mixins.font-body-small;
}
&__block-group { &__block-group {
color: variables.$color-accent-red; color: variables.$color-accent-red;
} }
@@ -350,6 +354,7 @@
flex-grow: 1; flex-grow: 1;
text-align: start; text-align: start;
margin-inline-end: 12px; margin-inline-end: 12px;
min-width: 0;
} }
&__info { &__info {
@@ -367,7 +372,7 @@
&__right { &__right {
position: relative; position: relative;
color: variables.$color-gray-45; color: variables.$color-gray-45;
min-width: 143px; min-width: 100px;
} }
&__actions { &__actions {

View File

@@ -180,6 +180,8 @@
min-height: 54px; min-height: 54px;
border-style: solid; border-style: solid;
border-width: 0 0 0 4px; border-width: 0 0 0 4px;
max-width: 100%;
} }
.module-quote__primary__author { .module-quote__primary__author {
@@ -189,6 +191,7 @@
align-items: center; align-items: center;
gap: 4px; gap: 4px;
max-width: 100%;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@@ -72,7 +72,7 @@ export function AnnouncementsOnlyGroupBanner({
/> />
</div> </div>
{labelString && contactNameColor && ( {labelString && contactNameColor && (
<div> <div className={tw('type-body-small')}>
<GroupMemberLabel <GroupMemberLabel
contactNameColor={contactNameColor} contactNameColor={contactNameColor}
contactLabel={{ contactLabel={{

View File

@@ -1,11 +1,14 @@
// Copyright 2023 Signal Messenger, LLC // Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import type { CSSProperties } from 'react';
import { Emojify } from './conversation/Emojify.dom.js'; import { Emojify } from './conversation/Emojify.dom.js';
import { bidiIsolate } from '../util/unicodeBidi.std.js'; import { bidiIsolate } from '../util/unicodeBidi.std.js';
export type UserTextProps = Readonly<{ export type UserTextProps = Readonly<{
text: string; text: string;
fontSizeOverride?: number;
style?: CSSProperties;
}>; }>;
export function UserText(props: UserTextProps): React.JSX.Element { export function UserText(props: UserTextProps): React.JSX.Element {
@@ -14,7 +17,11 @@ export function UserText(props: UserTextProps): React.JSX.Element {
}, [props.text]); }, [props.text]);
return ( return (
<span dir="auto"> <span dir="auto">
<Emojify text={normalizedText} /> <Emojify
fontSizeOverride={props.fontSizeOverride}
style={props.style}
text={normalizedText}
/>
</span> </span>
); );
} }

View File

@@ -25,6 +25,37 @@ export function FirstNameAndTitleFirstNamePreferred(): React.JSX.Element {
); );
} }
export function WithLongLabel(): React.JSX.Element {
return (
<div style={{ maxWidth: '400px', overflow: 'hidden' }}>
<ContactName
title="Troublemaker"
contactLabel={{
labelEmoji: '✅',
labelString:
"this is a long label. really long. why don't we see what happens?",
}}
contactNameColor="140"
/>
</div>
);
}
export function WithLabelWithBigUnicode(): React.JSX.Element {
return (
<div style={{ maxWidth: '400px', overflow: 'hidden' }}>
<ContactName
title="Troublemaker"
contactLabel={{
labelEmoji: '✅',
labelString: '𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫𒐫',
}}
contactNameColor="140"
/>
</div>
);
}
export function Colors(): React.JSX.Element { export function Colors(): React.JSX.Element {
return ( return (
<> <>

View File

@@ -6,7 +6,6 @@ import classNames from 'classnames';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { Emojify } from './Emojify.dom.js';
import { getClassNamesFor } from '../../util/getClassNamesFor.std.js'; import { getClassNamesFor } from '../../util/getClassNamesFor.std.js';
import { isSignalConversation as getIsSignalConversation } from '../../util/isSignalConversation.dom.js'; import { isSignalConversation as getIsSignalConversation } from '../../util/isSignalConversation.dom.js';
import { import {
@@ -22,6 +21,7 @@ import type { MemberLabelType } from '../../types/GroupMemberLabels.std.js';
import type { ConversationType } from '../../state/ducks/conversations.preload.js'; import type { ConversationType } from '../../state/ducks/conversations.preload.js';
import type { ContactNameColorType } from '../../types/Colors.std.js'; import type { ContactNameColorType } from '../../types/Colors.std.js';
import type { FunStaticEmojiSize } from '../fun/FunEmoji.dom.js'; import type { FunStaticEmojiSize } from '../fun/FunEmoji.dom.js';
import { UserText } from '../UserText.dom.js';
export type ContactNameData = { export type ContactNameData = {
contactNameColor?: ContactNameColorType; contactNameColor?: ContactNameColorType;
@@ -54,6 +54,7 @@ export function useContactNameData(
} }
export type PropsType = ContactNameData & { export type PropsType = ContactNameData & {
fontSizeOverride?: number;
module?: string; module?: string;
preferFirstName?: boolean; preferFirstName?: boolean;
onClick?: VoidFunction; onClick?: VoidFunction;
@@ -90,7 +91,7 @@ export function ContactName({
dir="auto" dir="auto"
onClick={onClick} onClick={onClick}
> >
<Emojify text={text} /> <UserText text={text} />
{(isSignalConversation || isMe) && ( {(isSignalConversation || isMe) && (
<span <span
className={ className={
@@ -187,7 +188,14 @@ export function GroupMemberLabel({
getClassName(`--label-pill--${context}--text`) getClassName(`--label-pill--${context}--text`)
)} )}
> >
<Emojify text={labelString} /> <UserText
fontSizeOverride={emojiSize}
style={{
verticalAlign: 'top',
marginTop: emojiSize / 6,
}}
text={labelString}
/>
</span> </span>
</span> </span>
</span> </span>

View File

@@ -1,6 +1,7 @@
// Copyright 2018 Signal Messenger, LLC // Copyright 2018 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'; import React from 'react';
import type { CSSProperties } from 'react';
import type { RenderTextCallbackType } from '../../types/Util.std.js'; import type { RenderTextCallbackType } from '../../types/Util.std.js';
import { splitByEmoji } from '../../util/emoji.std.js'; import { splitByEmoji } from '../../util/emoji.std.js';
import { missingCaseError } from '../../util/missingCaseError.std.js'; import { missingCaseError } from '../../util/missingCaseError.std.js';
@@ -23,6 +24,7 @@ export type Props = {
isInvisible?: boolean; isInvisible?: boolean;
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */ /** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
renderNonEmoji?: RenderTextCallbackType; renderNonEmoji?: RenderTextCallbackType;
style?: CSSProperties;
}; };
const defaultRenderNonEmoji: RenderTextCallbackType = ({ text }) => text; const defaultRenderNonEmoji: RenderTextCallbackType = ({ text }) => text;
@@ -31,6 +33,7 @@ export function Emojify({
fontSizeOverride, fontSizeOverride,
text, text,
renderNonEmoji = defaultRenderNonEmoji, renderNonEmoji = defaultRenderNonEmoji,
style,
}: Props): React.JSX.Element { }: Props): React.JSX.Element {
const emojiLocalizer = useFunEmojiLocalizer(); const emojiLocalizer = useFunEmojiLocalizer();
return ( return (
@@ -59,6 +62,7 @@ export function Emojify({
aria-label={emojiLocalizer.getLocaleShortName(variantKey)} aria-label={emojiLocalizer.getLocaleShortName(variantKey)}
emoji={variant} emoji={variant}
size={fontSizeOverride} size={fontSizeOverride}
style={style}
/> />
); );
} }

View File

@@ -141,7 +141,7 @@ export function ConversationDetailsMembershipList({
/> />
</div> </div>
{labelString && contactNameColor && ( {labelString && contactNameColor && (
<div> <div className="ConversationDetails-membership-list--member-label">
<GroupMemberLabel <GroupMemberLabel
contactNameColor={contactNameColor} contactNameColor={contactNameColor}
contactLabel={{ contactLabel={{

View File

@@ -153,6 +153,7 @@ export type FunInlineEmojiProps = FunImageAriaProps &
Readonly<{ Readonly<{
size?: number | null; size?: number | null;
emoji: EmojiVariantData; emoji: EmojiVariantData;
style?: CSSProperties;
}>; }>;
export function FunInlineEmoji(props: FunInlineEmojiProps): React.JSX.Element { export function FunInlineEmoji(props: FunInlineEmojiProps): React.JSX.Element {
@@ -175,6 +176,7 @@ export function FunInlineEmoji(props: FunInlineEmojiProps): React.JSX.Element {
{ {
'--fun-inline-emoji-size': '--fun-inline-emoji-size':
props.size != null ? `${props.size}px` : null, props.size != null ? `${props.size}px` : null,
...props.style,
} as CSSProperties } as CSSProperties
} }
> >