feat(app): render domain label in account overlay (#3424)

This commit is contained in:
omster authored and GitHub committed 2026-10-12 16:48:05 +02:00
1 parent 54f1b37666
commit b4fc1241ae
2 files changed
+74 -3

No files matched your search

@@ -7,6 +7,8 @@
--account-profile-instance-badge-size: 3rem; --account-profile-instance-badge-size: 3rem;
--account-profile-state-badge-size: 2.25rem; --account-profile-state-badge-size: 2.25rem;
--account-profile-name-color: var(--text-on-brand-primary); --account-profile-name-color: var(--text-on-brand-primary);
--account-profile-domain-height: 0;
--account-profile-domain-gap: 0;
--account-profile-name-gap: 0.625rem; --account-profile-name-gap: 0.625rem;
--account-profile-name-height: 1.5rem; --account-profile-name-height: 1.5rem;
--account-profile-more-size: 1.25rem; --account-profile-more-size: 1.25rem;
@@ -41,6 +43,12 @@
min-width: 0; min-width: 0;
} }
.tileSlotWithDomain {
--account-profile-domain-height: 1.1rem;
--account-profile-domain-gap: 0.3rem;
--account-profile-name-gap: 0.125rem;
}
.tile { .tile {
position: relative; position: relative;
z-index: 1; z-index: 1;
@@ -70,7 +78,12 @@
top: 100%; top: 100%;
right: 0; right: 0;
left: 0; left: 0;
height: calc(var(--account-profile-name-gap) + var(--account-profile-name-height)); height: calc(
var(--account-profile-domain-gap) +
var(--account-profile-domain-height) +
var(--account-profile-name-gap) +
var(--account-profile-name-height)
);
content: ''; content: '';
} }
@@ -99,7 +112,8 @@
color: var(--text-secondary); color: var(--text-secondary);
transition: transition:
background-color 40ms ease, background-color 40ms ease,
box-shadow 40ms ease; box-shadow 40ms ease,
transform 120ms ease-out;
} }
.avatarFrame::before { .avatarFrame::before {
@@ -134,6 +148,14 @@
box-shadow: 0 0 0 0.125rem color-mix(in srgb, var(--background-modifier-hover) 66%, var(--background-secondary)); box-shadow: 0 0 0 0.125rem color-mix(in srgb, var(--background-modifier-hover) 66%, var(--background-secondary));
} }
@media (prefers-reduced-motion: no-preference) {
:global(:where(html.window-focused, html.unfocused-fully-interactive):not(.window-focus-activation-guard))
.tile:not(:disabled):hover
.avatarFrame {
transform: scale(1.03);
}
}
.tileCurrent .avatarFrame::before { .tileCurrent .avatarFrame::before {
border-color: transparent; border-color: transparent;
} }
@@ -158,6 +180,28 @@
0 0 0 0.375rem color-mix(in srgb, var(--status-online) 20%, transparent); 0 0 0 0.375rem color-mix(in srgb, var(--status-online) 20%, transparent);
} }
.domainRow {
position: relative;
z-index: 2;
display: flex;
width: calc(100% - 0.5rem);
height: var(--account-profile-domain-height);
font-size: 0.85rem;
align-items: center;
justify-content: center;
color: var(--text-tertiary-muted);
gap: 0.1rem;
margin: var(--account-profile-domain-gap) auto 0;
pointer-events: none;
}
.domainRow > span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.nameRow { .nameRow {
position: relative; position: relative;
z-index: 2; z-index: 2;
@@ -154,6 +154,27 @@ function renderInstanceBadge({
); );
} }
interface RenderInstanceDomainArgs {
readonly instanceBadge: AccountInstanceBadgeInfo | null;
readonly showInstance: boolean;
}
function renderInstanceDomain({instanceBadge, showInstance}: RenderInstanceDomainArgs): React.ReactNode {
if (!showInstance || instanceBadge == null) {
return null;
}
return (
<div
className={styles.domainRow}
data-flx="auth.accounts.account-switcher-modal.account-profile-picker.render-instance-domain.domain-row"
>
<span data-flx="auth.accounts.account-switcher-modal.account-profile-picker.render-instance-domain.span">
{instanceBadge.title}
</span>
</div>
);
}
function renderExpiredAccountStatus(isExpired: boolean, statusLabel: string): React.ReactNode { function renderExpiredAccountStatus(isExpired: boolean, statusLabel: string): React.ReactNode {
if (!isExpired) { if (!isExpired) {
return null; return null;
@@ -238,6 +259,7 @@ const AccountProfileTile = observer(function AccountProfileTile({
const secondaryDisabled = disabled || resolveAccountPickerDisabled(secondaryActionDisabled, account, context); const secondaryDisabled = disabled || resolveAccountPickerDisabled(secondaryActionDisabled, account, context);
const selectLabel = resolveSelectLabel({i18n, showInstance, accountTag: tagLabel, instanceLabel}); const selectLabel = resolveSelectLabel({i18n, showInstance, accountTag: tagLabel, instanceLabel});
const removeLabel = i18n._(resolveRemoveAccountDescriptor(context.isCurrent), {accountTag: tagLabel}); const removeLabel = i18n._(resolveRemoveAccountDescriptor(context.isCurrent), {accountTag: tagLabel});
const instanceDomain = renderInstanceDomain({instanceBadge, showInstance});
const avatarFrameRef = useRef<HTMLSpanElement | null>(null); const avatarFrameRef = useRef<HTMLSpanElement | null>(null);
const handlePrimaryAction = useCallback(() => { const handlePrimaryAction = useCallback(() => {
if (primaryDisabled) { if (primaryDisabled) {
@@ -316,7 +338,11 @@ const AccountProfileTile = observer(function AccountProfileTile({
}; };
return ( return (
<div <div
className={clsx(styles.tileSlot, context.isExpired && styles.tileSlotExpired)} className={clsx(
styles.tileSlot,
context.isExpired && styles.tileSlotExpired,
instanceDomain != null && styles.tileSlotWithDomain,
)}
role="listitem" role="listitem"
data-flx="auth.accounts.account-switcher-modal.account-profile-picker.account-profile-tile.tile-slot" data-flx="auth.accounts.account-switcher-modal.account-profile-picker.account-profile-tile.tile-slot"
> >
@@ -357,6 +383,7 @@ const AccountProfileTile = observer(function AccountProfileTile({
</span> </span>
</button> </button>
</FocusRing> </FocusRing>
{instanceDomain}
<div <div
className={styles.nameRow} className={styles.nameRow}
data-flx="auth.accounts.account-switcher-modal.account-profile-picker.account-profile-tile.name-row" data-flx="auth.accounts.account-switcher-modal.account-profile-picker.account-profile-tile.name-row"