directus on GitHub

directus/directus

Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.

30 files reviewed·August 1, 2026

View on GitHub

Elevated

Design risk in this codebase.

4issues
Critical, Serious & Moderate · top 3 shown below

Top fix

Add a keyboard focus trigger alongside hover on the VMenu

See the fix

Verdict

Visual polish outpaces accessibility follow-through: stacked avatars and tooltips look considered, but hover-only reveals lock keyboard users out entirely. The biggest risk is that the feature's core value, seeing who's editing, is unreachable without a mouse.

Files Rams reviewed

app/src/views/private/components/FolderPickerListItem.vue

app/src/views/private/components/archive-sidebar-detail.vue

app/src/views/private/components/basic-import-sidebar-detail.vue

app/src/views/private/components/collab/CollabIndicatorField.vue

app/src/views/private/components/collab/CollabIndicatorHeader.vue

app/src/views/private/components/comment-input.vue

app/src/views/private/components/comment-item-header.vue

app/src/views/private/components/comment-item.vue

app/src/views/private/components/comments-sidebar-detail.vue

app/src/views/private/components/comparison/comparison-header.vue

app/src/views/private/components/comparison/comparison-toggle.vue

app/src/views/private/components/drawer-batch.vue

app/src/views/private/components/drawer-collection.vue

app/src/views/private/components/drawer-files.vue

app/src/views/private/components/file-lightbox.vue

app/src/views/private/components/file-preview-replace.vue

app/src/views/private/components/file-preview.vue

app/src/views/private/components/files-navigation-folder.vue

app/src/views/private/components/files-navigation.vue

app/src/views/private/components/flow-dialogs.vue

app/src/views/private/components/flow-sidebar-detail.vue

app/src/views/private/components/folder-picker.vue

app/src/views/private/components/import-error-dialog.vue

app/src/views/private/components/layout-sidebar-detail.vue

app/src/views/private/components/license-banner.vue

app/src/views/private/components/license-onboarding.vue

app/src/views/private/components/license-resolution-prompt.vue

app/src/views/private/components/license-upgrade-modal.vue

app/src/views/private/components/license/entitlement-limit-modal.vue

app/src/views/private/components/license/entitlement-remaining.vue

95/100

Accessibility

1 critical1 serious
AccessibilityCritical

app/src/views/private/components/collab/CollabIndicatorHeader.vue:62

Collaborator status only ever reveals on mouse hover

In CollabIndicatorHeader.vue, `<VMenu trigger="hover" show-arrow invert>` gates the collaborator name and 'currently editing'/'currently viewing' status text behind hover only. The activator VAvatar is only conditionally :clickable when the user has a focusedField, so keyboard users tabbing through the header have no way to trigger the hover-only popover for most collaborators.

Why it matters

Keyboard-only and touch users can never see who is viewing or editing the field, since the only trigger is mouse hover, which locks an entire input method out of information sighted mouse users get for free.

Fix

Add a focus trigger alongside hover (or make the activator a real button with focus/keydown handling) so the same status surfaces on keyboard focus.

<VMenu trigger="hover" show-arrow invert>
<VMenu trigger="hover focus" show-arrow invert>
AccessibilitySerious

app/src/views/private/components/collab/CollabIndicatorHeader.vue:72

Same unlabeled avatar pattern repeats twice in the header, and again in the overflow list

CollabIndicatorHeader.vue renders `<img v-if="user.avatar_url" :src="user.avatar_url" />` for the visible collaborator row (line 72) and again for every item in the 'more users' overflow list (line 116), neither with an alt attribute.

Why it matters

Every collaborator avatar in both the visible row and the overflow popover is invisible to assistive tech, so a screen reader user browsing the collab header gets no names at all, only 'image'.

Fix

Give both img instances alt text bound to the same user.name fallback already used in the adjacent tooltip content.

<img v-if="user.avatar_url" :src="user.avatar_url" />
<img v-if="user.avatar_url" :src="user.avatar_url" :alt="user.name ?? t('unknown_user')" />
98/100

Typography

1 serious
TypographySerious

app/src/views/private/components/collab/CollabIndicatorHeader.vue:160

Avatar initials render below the 12px legibility floor

The `.collab-header, .collab-header-more-popover-item` scoped style sets `:deep(.v-avatar) { font-size: 0.6875rem; }`, which is 11px. This applies to the single-letter initials shown when a collaborator has no avatar_url.

Why it matters

At 11px, single-character initials in a small circular avatar are hard to distinguish for users with low vision, and this text has no way to reflow or zoom independently of the fixed avatar size.

Fix

Raise avatar initials to at least 12px (0.75rem) to clear the small-text legibility floor.

font-size: 0.6875rem;
font-size: 0.75rem;

Color

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

UX

No issues found

Craft

No issues found

Working well

  • Binding v-tooltip to `user.name ?? t('unknown_user')` on each VAvatar gives every collaborator indicator a discoverable, localized label on hover, a solid pattern to extend once the underlying img also gets alt text.
  • Stacking avatars with `:style="{ zIndex: visibleUsers.length - index }"` correctly layers earlier collaborators above later ones, producing a clean overlapping row without any z-index collisions.
  • The radio group in the same component family binds label text via `item.text` with model-value/update:model-value, keeping VRadio fully controlled and accessible without any custom click wiring.

Scored August 1, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored May 13, 2026: 59/100. This rescore on v0.0.3: 59/100.

This page is an automated design review of directus/directus’s UI code: 30 files read against 348 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.

More design scores

Score your own repo.

Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.

Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.

Or get a design review on every pull requestInstall Rams