Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion apps/quill/client/components/playground-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ export function PlaygroundView({
<div className="mb-6 grid gap-3 md:grid-cols-3">
<Control label="Guide">
<select
aria-label="Guide"
className="pp-select"
Comment on lines 297 to 299

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the <select> element is already wrapped inside a <label> element by the Control component, it is implicitly associated and will be correctly announced by screen readers. Adding a hardcoded aria-label is redundant and introduces a maintenance risk where the visual label and the accessible name could desync (violating WCAG 2.5.3 Label in Name if they diverge).

Suggested change
<select
aria-label="Guide"
className="pp-select"
<select
className="pp-select"

onChange={(e) => setGuideSlug(e.target.value)}
value={guideSlug}
Expand All @@ -309,6 +310,7 @@ export function PlaygroundView({

<Control label="Preset">
<select
aria-label="Preset"
className="pp-select"
Comment on lines 312 to 314

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the Guide selector, this <select> is already wrapped in a <label> via the Control component. The aria-label is redundant and risks desyncing from the visual label.

Suggested change
<select
aria-label="Preset"
className="pp-select"
<select
className="pp-select"

onChange={(e) => setPresetSlug(e.target.value as UseCase | "")}
value={presetSlug}
Expand Down Expand Up @@ -341,7 +343,8 @@ export function PlaygroundView({
<div className="grid gap-5 md:grid-cols-2">
<Panel label="Input">
<textarea
className="min-h-[220px] w-full resize-y bg-transparent text-sm focus:outline-none"
aria-label="Input"
className="min-h-[220px] w-full resize-y bg-transparent text-sm focus:outline-none focus-visible:outline-[var(--strand-color-accent-lede)] focus-visible:outline-2 focus-visible:outline-offset-2"
onChange={(e) => setInput(e.target.value)}
placeholder="Paste a customer message, a prompt, a paragraph to rewrite…"
style={{ color: "var(--strand-color-ink-primary)" }}
Expand Down Expand Up @@ -647,6 +650,11 @@ export function PlaygroundView({
border-radius: 0.375rem;
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
outline: none;
}
.pp-select:focus-visible {
outline: 2px solid var(--strand-color-accent-lede);
outline-offset: 2px;
}
Comment on lines +653 to 658

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Setting outline: none on the base .pp-select class removes the outline entirely for all states, which can cause unexpected accessibility issues if :focus-visible is not triggered or supported. It is safer and more idiomatic to only remove the outline on :focus, matching the Tailwind behavior used on the textarea above.

        }
        .pp-select:focus {
          outline: none;
        }
        .pp-select:focus-visible {
          outline: 2px solid var(--strand-color-accent-lede);
          outline-offset: 2px;
        }

`}</style>
</section>
Expand Down
Loading