style(editor): align byline dictation mic with the info icon

The byline mic rendered blue and with a smaller (16px) glyph next to the
gray 20px info icon, so it looked misaligned with an uneven gap. Add
optional color/iconSize props to MicButton (forwarded through
DictationGroup) and render the byline mic gray at 20px, wrapping it and
the info icon in a tight nowrap group so they read as a snug, aligned
pair. The AI chat mic is unchanged (passes neither prop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude_code
2026-06-22 02:48:50 +03:00
parent 3a3d22ac55
commit ef74058301
3 changed files with 34 additions and 17 deletions

View File

@@ -12,6 +12,11 @@ interface MicButtonProps {
// Mantine ActionIcon size token; "lg" matches the chat composer, "md" the
// editor toolbar.
size?: "md" | "lg";
// Optional Mantine color override for the idle/transcribing states (the
// recording state stays red). Defaults to the theme primary when omitted.
color?: string;
// Optional explicit glyph size override; defaults to the size-token value.
iconSize?: number;
}
/**
@@ -25,10 +30,12 @@ export const MicButton: FC<MicButtonProps> = ({
onStart,
disabled,
size = "lg",
color,
iconSize,
}) => {
const { t } = useTranslation();
const { status, start, stop, audioLevel } = useDictation({ onText, onStart });
const iconSize = size === "lg" ? 18 : 16;
const resolvedIconSize = iconSize ?? (size === "lg" ? 18 : 16);
if (status === "recording") {
// Live volume-driven halo: the scale follows the current mic level.
@@ -49,7 +56,7 @@ export const MicButton: FC<MicButtonProps> = ({
aria-label={t("Stop recording")}
style={{ position: "relative", zIndex: 1 }}
>
<IconPlayerStopFilled size={iconSize} />
<IconPlayerStopFilled size={resolvedIconSize} />
</ActionIcon>
</span>
</Tooltip>
@@ -62,6 +69,7 @@ export const MicButton: FC<MicButtonProps> = ({
<ActionIcon
size={size}
variant="subtle"
color={color}
disabled
aria-label={t("Transcribing…")}
>
@@ -76,11 +84,12 @@ export const MicButton: FC<MicButtonProps> = ({
<ActionIcon
size={size}
variant="subtle"
color={color}
onClick={() => void start()}
disabled={disabled}
aria-label={t("Start dictation")}
>
<IconMicrophone size={iconSize} />
<IconMicrophone size={resolvedIconSize} />
</ActionIcon>
</Tooltip>
);

View File

@@ -4,9 +4,11 @@ import { MicButton } from "@/features/dictation/components/mic-button";
interface Props {
editor: Editor;
color?: string;
iconSize?: number;
}
export const DictationGroup: FC<Props> = ({ editor }) => {
export const DictationGroup: FC<Props> = ({ editor, color, iconSize }) => {
const rangeRef = useRef<{ from: number; to: number } | null>(null);
const handleStart = () => {
@@ -56,6 +58,8 @@ export const DictationGroup: FC<Props> = ({ editor }) => {
onStart={handleStart}
onText={handleText}
disabled={!editor.isEditable}
color={color}
iconSize={iconSize}
/>
);
};

View File

@@ -222,6 +222,7 @@ function PageByline({
</Popover.Dropdown>
</Popover>
)}
<Group gap={4} wrap="nowrap">
<Tooltip label={t("Details")} withArrow openDelay={250}>
<ActionIcon
variant="subtle"
@@ -234,7 +235,10 @@ function PageByline({
</Tooltip>
{/* Shown only in edit mode when workspace dictation is enabled, so
dictation stays reachable even when the fixed toolbar is hidden. */}
{showDictation && editor && <DictationGroup editor={editor} />}
{showDictation && editor && (
<DictationGroup editor={editor} color="gray" iconSize={20} />
)}
</Group>
</Group>
);
}