diff --git a/web/docs/truncated-text-disclosure.md b/web/docs/truncated-text-disclosure.md index cb159e2cfbc..6262b0c86ba 100644 --- a/web/docs/truncated-text-disclosure.md +++ b/web/docs/truncated-text-disclosure.md @@ -2,6 +2,8 @@ Treat native `title` as an opt-in, supplemental product behavior. Do not treat it as a mechanical companion to `truncate`, `text-overflow`, or `line-clamp-*`. +Browser-rendered title tooltips are exempt from the author-controlled hover and focus behavior in [WCAG 1.4.13], but that exception is not an accessibility endorsement. [MDN] documents unreliable access for touch, keyboard, and assistive-technology users. The classifications below decide whether to add `title`; they do not establish WCAG conformance for the surrounding interaction. + Missing `title` is not by itself an accessibility defect. Native title tooltips must not: - be the only way to access essential information; @@ -12,7 +14,7 @@ Before making a change: 1. Trace the value to the final rendered DOM element. 2. Identify the existing owner of full-content disclosure. -3. Classify the candidate as `AUTO`, `COVERED`, `SKIP`, or `REVIEW`. +3. Apply `SKIP`, `COVERED`, `AUTO`, and `REVIEW` in that order, stopping at the first matching classification. 4. Modify only `AUTO` candidates. Report the others without changing code. ## AUTO @@ -22,17 +24,20 @@ Automatically add `title` only when every condition below is satisfied: - The target is a native, non-editable, pointer-reachable text container whose own hit area receives the pointer, or a documented component that forwards `title` unchanged to that final DOM element. - The final element intentionally implements single-line truncation. A truncation-related class alone is not sufficient evidence. - The full content is a bounded, non-sensitive, single-line plain string. +- The truncated portion is supplemental; users do not need it to understand, distinguish, or complete the current task. - “Bounded” means fixed text, an enum, or a value with an explicit owner-level maximum length. - The exact already-evaluated display value can be reused without repeating a function call, getter, conversion, mutation, async operation, or other potentially effectful expression. - The final rendered element does not already receive an equivalent title through its props, wrapper, child component, or covering interaction target. -- No Tooltip, PreviewCard, Popover, expandable content, “show more” action, detail view, copy/reveal action, or other full-content owner exists. +- No Tooltip, Popover, expandable content, “show more” action, detail view, copy/reveal action, or other full-content owner exists. A PreviewCard counts only under the `COVERED` rule below. - The native tooltip will not compete with another hover, focus, pointer, or keyboard interaction. ## COVERED -Classify as `COVERED` and make no change when another component or interaction already owns full-content disclosure, including: +Classify as `COVERED` and make no change when the full content is already available through the current content, an accessible interaction, or a linked destination. An overlay is not automatically a disclosure owner: -- Tooltip, PreviewCard, or Popover; +- a Tooltip only when it duplicates non-essential full text already available from its trigger's readable text or accessible name; +- a [PreviewCard] whose trigger is a real destination link and whose destination contains the equivalent full content; the preview popup itself is only a visual enhancement, not the disclosure owner; +- a Popover that exposes the full content through pointer, keyboard, touch, and assistive technology; - expandable or “show more” content; - a detail view opened from the current surface; - a copy or reveal action; @@ -48,16 +53,18 @@ Classify as `SKIP` and make no change when any condition below applies: - Producing the title would repeat or relocate evaluation of a function call, getter, conversion, mutation, async operation, or other potentially effectful expression. - The element is an input, textarea, editable surface, `pointer-events-none`, covered by another element, or not the actual pointer target. - An existing `title`, including `title=""`, would need to be overwritten or removed. -- The content uses `line-clamp-*` and already has an expand or detail interaction. ## REVIEW Classify as `REVIEW`, make no code change, and report the reason when: - the correct disclosure owner is ambiguous or product-specific; +- users need the full value to understand, distinguish, or complete the task, but no cross-input disclosure owner exists; - the value bound or sensitivity cannot be proven; - the final DOM element or pointer owner cannot be traced; - the component is interactive; +- Tooltip or PreviewCard content would be the only path to the full content, or a PreviewCard trigger is not a destination link; +- a Popover or other disclosure cannot be reached across pointer, keyboard, touch, and assistive technology; - the content uses `line-clamp-*` without an existing full-content path; - actual truncation or the intended product behavior cannot be established from the owner contract. @@ -71,3 +78,7 @@ Do not introduce: - suppressions for candidates outside the allowlist. Test the feature-owned disclosure behavior through its public interface. Assert native `title` only when it is an explicitly accepted product contract. Do not use `getByTitle` or `toHaveAttribute('title', ...)` merely to prove a migration, and do not use title-based selectors to test unrelated interactions. + +[MDN]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/title#accessibility_concerns +[PreviewCard]: ../../packages/dify-ui/docs/overlays.md#primitive-semantics +[WCAG 1.4.13]: https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html