View Once UI Updates

Co-authored-by: yash-signal <yash@signal.org>
This commit is contained in:
automated-signal
2026-03-05 13:48:20 -06:00
committed by GitHub
parent 9861418df7
commit 1120647b92
8 changed files with 102 additions and 81 deletions

View File

@@ -40,18 +40,10 @@
height: 20px;
width: 20px;
@include mixins.light-theme {
@include mixins.color-svg(
'../images/icons/v3/mic/mic.svg',
variables.$color-gray-75
);
}
@include mixins.dark-theme {
@include mixins.color-svg(
'../images/icons/v3/mic/mic.svg',
variables.$color-gray-15
);
}
@include mixins.color-svg(
'../images/icons/v3/mic/mic.svg',
var(--color-label-primary)
);
}
}

View File

@@ -8,6 +8,7 @@
&__popper {
@include mixins.module-composition-popper;
& {
color: var(--color-label-primary);
padding-block: 12px;
padding-inline: 16px;
width: auto;
@@ -42,7 +43,7 @@
&--selected {
@include mixins.color-svg(
'../images/icons/v3/check/check-compact.svg',
variables.$color-ultramarine
currentColor
);
}

View File

@@ -39,13 +39,13 @@
.FunButton__Icon--EmojiPicker {
@include mixins.color-svg(
'../images/icons/v3/emoji/emoji.svg',
light-dark(variables.$color-gray-75, variables.$color-gray-15)
var(--color-label-primary)
);
}
.FunButton__Icon--StickerPicker {
@include mixins.color-svg(
'../images/icons/v3/sticker/sticker.svg',
light-dark(variables.$color-gray-75, variables.$color-gray-15)
var(--color-label-primary)
);
}

View File

@@ -112,6 +112,7 @@ export namespace AxoIconButton {
variant: Variant;
size: Size;
symbol: AxoSymbol.IconName;
iconWeight?: AxoSymbol.Weight;
experimentalSpinner?: { 'aria-label': string } | null;
@@ -130,6 +131,7 @@ export namespace AxoIconButton {
variant,
size,
symbol,
iconWeight,
experimentalSpinner,
...rest
} = props;
@@ -166,6 +168,7 @@ export namespace AxoIconButton {
size={Sizes[size].iconSize}
symbol={symbol}
label={null}
weight={iconWeight}
/>
</span>
{experimentalSpinner != null && (

View File

@@ -4,6 +4,7 @@ import type { FC } from 'react';
import React, { memo, useMemo } from 'react';
import { Direction } from 'radix-ui';
import { VisuallyHidden } from 'react-aria';
import type { TailwindStyles } from './tw.dom.js';
import { tw } from './tw.dom.js';
import {
getAxoSymbolIcon,
@@ -21,15 +22,22 @@ const Namespace = 'AxoSymbol';
export namespace AxoSymbol {
const symbolStyles = tw('font-symbols select-none');
const labelStyles = tw('select-none');
export type Weight = 300 | 400 | 700;
const WeightStyles = {
300: tw('font-light'),
400: tw(),
700: tw('font-semibold'),
} as const satisfies Record<Weight, TailwindStyles>;
function useRenderSymbol(
glyph: string,
label: string | null
label: string | null,
weight: Weight
): React.JSX.Element {
return useMemo(() => {
return (
<>
<span aria-hidden className={symbolStyles}>
<span aria-hidden className={tw(symbolStyles, WeightStyles[weight])}>
{glyph}
</span>
{label != null && (
@@ -37,7 +45,7 @@ export namespace AxoSymbol {
)}
</>
);
}, [glyph, label]);
}, [glyph, label, weight]);
}
/**
@@ -55,7 +63,7 @@ export namespace AxoSymbol {
export const InlineGlyph: FC<InlineGlyphProps> = memo(props => {
const direction = useDirection();
const glyph = getAxoSymbolInlineGlyph(props.symbol, direction);
const content = useRenderSymbol(glyph, props.label);
const content = useRenderSymbol(glyph, props.label, 400);
return content;
});
@@ -89,6 +97,7 @@ export namespace AxoSymbol {
size: IconSize;
symbol: IconName;
label: string | null;
weight?: Weight;
}>;
const iconStyles = tw(
@@ -98,8 +107,9 @@ export namespace AxoSymbol {
export const Icon: FC<IconProps> = memo(props => {
const config = IconSizes[props.size];
const direction = useDirection();
const weight = props.weight ?? 400;
const glyph = getAxoSymbolIcon(props.symbol, direction);
const content = useRenderSymbol(glyph, props.label);
const content = useRenderSymbol(glyph, props.label, weight);
const style = useMemo(() => {
return {

View File

@@ -1084,6 +1084,7 @@ export function CompositionInput(props: Props): React.ReactElement {
<AxoSymbol.Icon
size={20}
symbol={isViewOnceActive ? 'viewonce' : 'viewonce-slash'}
weight={300}
label={null}
/>
</button>

View File

@@ -1380,6 +1380,7 @@ export function MediaEditor({
i18n={i18n}
isHighQuality={localIsHighQuality}
onSelectQuality={handleSelectQuality}
theme={pickerTheme}
/>
</div>
)}

View File

@@ -6,6 +6,7 @@ import React, { useCallback, useRef, useState } from 'react';
import classNames from 'classnames';
import { Popover } from 'radix-ui';
import type { LocalizerType } from '../types/Util.std.js';
import { ThemeType } from '../types/Util.std.js';
import { AxoIconButton } from '../axo/AxoIconButton.dom.js';
export type PropsType = {
@@ -13,6 +14,7 @@ export type PropsType = {
i18n: LocalizerType;
isHighQuality: boolean;
onSelectQuality: (conversationId: string, isHQ: boolean) => unknown;
theme?: ThemeType;
};
export function MediaQualitySelector({
@@ -20,6 +22,7 @@ export function MediaQualitySelector({
i18n,
isHighQuality,
onSelectQuality,
theme,
}: PropsType): React.JSX.Element {
const [open, setOpen] = useState(false);
const standardRef = useRef<HTMLButtonElement>(null);
@@ -56,78 +59,88 @@ export function MediaQualitySelector({
variant="borderless-secondary"
size="md"
symbol={isHighQuality ? 'hd' : 'hd-slash'}
iconWeight={300}
label={i18n('icu:MediaQualitySelector--button')}
tooltip={false}
/>
</Popover.Trigger>
{open && (
<Popover.Portal>
<Popover.Content
className="MediaQualitySelector__popper"
side="top"
align="start"
sideOffset={4}
onOpenAutoFocus={handleOpenAutoFocus}
onKeyDown={handleContentKeyDown}
<div
className={classNames({
'light-theme': theme === ThemeType.light,
'dark-theme': theme === ThemeType.dark,
})}
>
<div className="MediaQualitySelector__title">
{i18n('icu:MediaQualitySelector--title')}
</div>
<button
ref={standardRef}
aria-label={i18n(
'icu:MediaQualitySelector--standard-quality-title'
)}
className="MediaQualitySelector__option"
type="button"
onClick={() => {
onSelectQuality(conversationId, false);
setOpen(false);
}}
<Popover.Content
className="MediaQualitySelector__popper"
side="top"
align="start"
sideOffset={4}
onOpenAutoFocus={handleOpenAutoFocus}
onKeyDown={handleContentKeyDown}
>
<div
className={classNames({
'MediaQualitySelector__option--checkmark': true,
'MediaQualitySelector__option--selected': !isHighQuality,
})}
/>
<div>
<div className="MediaQualitySelector__option--title">
{i18n('icu:MediaQualitySelector--standard-quality-title')}
</div>
<div className="MediaQualitySelector__option--description">
{i18n(
'icu:MediaQualitySelector--standard-quality-description'
)}
</div>
<div className="MediaQualitySelector__title">
{i18n('icu:MediaQualitySelector--title')}
</div>
</button>
<button
ref={highRef}
aria-label={i18n('icu:MediaQualitySelector--high-quality-title')}
className="MediaQualitySelector__option"
type="button"
onClick={() => {
onSelectQuality(conversationId, true);
setOpen(false);
}}
>
<div
className={classNames({
'MediaQualitySelector__option--checkmark': true,
'MediaQualitySelector__option--selected': isHighQuality,
})}
/>
<div>
<div className="MediaQualitySelector__option--title">
{i18n('icu:MediaQualitySelector--high-quality-title')}
<button
ref={standardRef}
aria-label={i18n(
'icu:MediaQualitySelector--standard-quality-title'
)}
className="MediaQualitySelector__option"
type="button"
onClick={() => {
onSelectQuality(conversationId, false);
setOpen(false);
}}
>
<div
className={classNames({
'MediaQualitySelector__option--checkmark': true,
'MediaQualitySelector__option--selected': !isHighQuality,
})}
/>
<div>
<div className="MediaQualitySelector__option--title">
{i18n('icu:MediaQualitySelector--standard-quality-title')}
</div>
<div className="MediaQualitySelector__option--description">
{i18n(
'icu:MediaQualitySelector--standard-quality-description'
)}
</div>
</div>
<div className="MediaQualitySelector__option--description">
{i18n('icu:MediaQualitySelector--high-quality-description')}
</button>
<button
ref={highRef}
aria-label={i18n(
'icu:MediaQualitySelector--high-quality-title'
)}
className="MediaQualitySelector__option"
type="button"
onClick={() => {
onSelectQuality(conversationId, true);
setOpen(false);
}}
>
<div
className={classNames({
'MediaQualitySelector__option--checkmark': true,
'MediaQualitySelector__option--selected': isHighQuality,
})}
/>
<div>
<div className="MediaQualitySelector__option--title">
{i18n('icu:MediaQualitySelector--high-quality-title')}
</div>
<div className="MediaQualitySelector__option--description">
{i18n('icu:MediaQualitySelector--high-quality-description')}
</div>
</div>
</div>
</button>
</Popover.Content>
</button>
</Popover.Content>
</div>
</Popover.Portal>
)}
</Popover.Root>