mirror of
https://github.com/vxcontrol/pentagi.git
synced 2026-08-26 13:06:32 +00:00
fix(markdown-editor): give the link edit-form label/aria-describedby parity
The link edit-form relied on a placeholder + aria-label with no visible <Label>, and its invalid-URL alert had no aria-describedby back to the input — both present on the sibling image edit-form. A screen-reader user who tabbed onto the field after the error fired never heard why it was invalid. Add a visible Label (via useId) and wire aria-describedby to the error id, matching ImageEditForm. Also trim two comments per the zero-comment rule: the normalizeLinkUrl-return restatement (documented at the callee) and the "(matches Docs/Notion)" competitor-justification. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
215c1cd8c9
commit
fde073e393
@@ -1,9 +1,10 @@
|
||||
import type { Editor } from '@tiptap/react';
|
||||
|
||||
import { ArrowUpRight, Check, Trash2 } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from '@/components/ui/input-group';
|
||||
import { Label } from '@/components/ui/label';
|
||||
|
||||
import { normalizeLinkUrl } from './markdown-editor-toolbar-url';
|
||||
|
||||
@@ -22,8 +23,9 @@ interface LinkEditFormProps {
|
||||
// mount, so consumers give it a fresh `key` per editing session.
|
||||
export function LinkEditForm({ autoFocus = true, editor, initialUrl, isActive, onDone }: LinkEditFormProps) {
|
||||
const [url, setUrl] = useState(initialUrl);
|
||||
const urlId = useId();
|
||||
const errorId = useId();
|
||||
|
||||
// Normalized absolute href (scheme prepended, protocol validated) or null when the input is unsafe/empty.
|
||||
const href = normalizeLinkUrl(url);
|
||||
const isInvalid = url !== '' && href === null;
|
||||
|
||||
@@ -35,8 +37,8 @@ export function LinkEditForm({ autoFocus = true, editor, initialUrl, isActive, o
|
||||
const { empty } = editor.state.selection;
|
||||
|
||||
if (empty && !isActive) {
|
||||
// No selection to wrap → insert the URL as its own linked text (matches Docs/Notion). Shows what the
|
||||
// user typed but links to the normalized href.
|
||||
// No selection to wrap → insert the URL as its own linked text: the visible text is what the user
|
||||
// typed, but the href is the normalized value.
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
@@ -62,11 +64,13 @@ export function LinkEditForm({ autoFocus = true, editor, initialUrl, isActive, o
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor={urlId}>Link URL</Label>
|
||||
<InputGroup>
|
||||
<InputGroupInput
|
||||
aria-describedby={isInvalid ? errorId : undefined}
|
||||
aria-invalid={isInvalid}
|
||||
aria-label="Link URL"
|
||||
autoFocus={autoFocus}
|
||||
id={urlId}
|
||||
onChange={(event) => setUrl(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
@@ -112,6 +116,7 @@ export function LinkEditForm({ autoFocus = true, editor, initialUrl, isActive, o
|
||||
{isInvalid ? (
|
||||
<p
|
||||
className="text-destructive text-xs"
|
||||
id={errorId}
|
||||
role="alert"
|
||||
>
|
||||
Only http, https, mailto and tel links are allowed.
|
||||
|
||||
Reference in New Issue
Block a user