Skip to content

Require IDs for dropdowns#22

Merged
ukutaht merged 3 commits intomainfrom
require-ids-for-dropdown
Feb 11, 2026
Merged

Require IDs for dropdowns#22
ukutaht merged 3 commits intomainfrom
require-ids-for-dropdown

Conversation

@ukutaht
Copy link
Contributor

@ukutaht ukutaht commented Feb 11, 2026

No description provided.

@claude
Copy link

claude bot commented Feb 11, 2026

PR Review: Require IDs for Dropdowns

Summary

This PR shifts from auto-generating IDs in JavaScript to requiring explicit IDs for all dropdown components. This is a solid architectural decision that improves maintainability and accessibility.

Code Quality & Best Practices ✅

Strengths

  1. Cleaner separation of concerns - Removes complex auto-generation logic from JavaScript hook (dropdown.js:330-350 deleted)
  2. More predictable ARIA relationships - IDs are now explicit and traceable in templates rather than dynamically generated
  3. Consistent with library philosophy - Developers maintain full control over component structure
  4. Well-documented - Component documentation updated with clear examples showing required IDs

Code Organization

  • Elixir changes are well-structured with clear required: true attributes
  • JavaScript simplification is clean - removed ~30 lines of ID generation complexity
  • Examples properly updated to show the new pattern with Enum.with_index/1

Accessibility ✅

Excellent accessibility improvements:

  1. ARIA relationships are now explicit (dropdown.js:333-334):

    button.setAttribute('aria-controls', menu.id)
    menu.setAttribute('aria-labelledby', button.id)

    No more auto-generated IDs that could be unpredictable

  2. Section labeling remains intact (dropdown.js:339-349):

    • Still properly links [role="group"] sections to heading IDs via aria-labelledby
    • Test coverage confirms this works correctly (dropdown_sections_test.exs:36-48)
  3. Keyboard navigation unaffected - Tests verify navigation still works properly

Test Coverage ✅

Strong test updates:

The test file changes (dropdown_sections_test.exs:36-48) show good attention to detail - changed from auto-generated ID pattern checking to explicit ID verification. This is more robust.

Potential Issues & Considerations

1. Breaking Change ⚠️

This is a breaking change for existing users. Any code using dropdowns without explicit IDs will now fail at compile time with missing required parameter errors.

Recommendation:

  • Document this clearly in the changelog/release notes
  • Consider if this warrants a major version bump (1.0.0 → 2.0.0)
  • Add a migration guide showing before/after examples

2. Developer Experience Consideration

The need to manually track indices when using :for comprehensions adds some boilerplate. Have you considered providing a convenience helper or documenting a recommended pattern for this common case?

3. ID Uniqueness Validation

Currently there's no runtime validation that IDs are unique. If a developer accidentally uses duplicate IDs, the ARIA relationships will break silently.

Suggestion (future enhancement):
Consider adding development-mode warnings when duplicate IDs are detected within a dropdown component.

Performance ✅

Positive impact:

  • Removed ID generation logic reduces initialization overhead
  • Simpler setupAriaRelationships function (dropdown.js:332-337) is more efficient
  • No performance regressions expected

Security ✅

No security concerns identified. The change actually reduces attack surface by removing dynamic ID generation.

Final Recommendation

Approve with suggestions

This is a well-executed refactoring that improves code clarity and maintainability. The main consideration is ensuring the breaking change is well-communicated to users.

Action Items:

  1. ✅ Document as breaking change in release notes
  2. 💡 Consider adding migration guide
  3. 💡 Consider documenting recommended patterns for dynamic lists
  4. 💡 Future: Consider development-mode ID uniqueness validation

The code quality is high, tests are comprehensive, and the architectural direction is sound. Great work simplifying the JavaScript while maintaining full accessibility compliance!

@claude
Copy link

claude bot commented Feb 11, 2026

Code Review: Require IDs for Dropdowns

Overview

This PR transitions the dropdown component from auto-generating IDs in JavaScript to requiring explicit IDs at the component level. This is a breaking change that improves code clarity and aligns with the library's design philosophy.

✅ Strengths

1. Architectural Improvement

The removal of ~30 lines of ID generation logic from the JavaScript hook (assets/js/hooks/dropdown.js:330-350) significantly simplifies the codebase:

  • Removes setupMenuitemIds() entirely
  • Simplifies setupAriaRelationships() to just set attributes directly
  • Makes ARIA relationships explicit and traceable in templates

2. Consistency with Prima Design Philosophy

This change aligns well with Prima's "unstyled, developer-controlled" approach. By requiring explicit IDs, developers have full visibility and control over component structure, which is consistent with how Modal and Combobox components already work.

3. Documentation & Examples

All code examples have been thoroughly updated with clear patterns:

  • Simple cases: explicit IDs (lib/prima/dropdown.ex:40-42)
  • Dynamic lists: Enum.with_index/1 pattern (demo/priv/code_examples/dropdown/basic.html.heex:22-23)
  • Component documentation clearly indicates required IDs

4. Test Coverage

The test update in demo/test/wallaby/demo_web/dropdown_sections_test.exs:36-48 improves from pattern-based assertions to explicit ID verification, which is more robust.

⚠️ Concerns & Recommendations

1. Breaking Change Communication (Critical)

Issue: This is a major breaking change. Any existing dropdown usage without explicit IDs will fail at compile time.

Recommendation:

  • Add a prominent CHANGELOG entry documenting this breaking change
  • Consider if this warrants a major version bump
  • Include migration examples in the release notes

2. Developer Ergonomics for Dynamic Lists

Observation: The Enum.with_index/1 pattern for dynamic lists adds boilerplate (demo/priv/code_examples/dropdown/basic.html.heex:22-23):

<.dropdown_item
  :for={{option, index} <- Enum.with_index(["Account settings", "Billing", "Documentation"])}
  id={"basic-dropdown-item-#{index}"}
  class="..."
>
  {option}
</.dropdown_item>

Suggestion: Document this as the recommended pattern for dynamic lists in the module docs or README. This is a common use case and deserves clear guidance.

3. Accessibility - Section Headings

Question: In lib/prima/dropdown.ex:346, the setupSectionLabels() function assumes heading IDs exist. What happens if a developer forgets to add an ID to a dropdown_heading?

section.setAttribute('aria-labelledby', firstChild.id)

If firstChild.id is undefined, this could set aria-labelledby="" which may cause accessibility issues.

Recommendation: Consider adding a runtime check or warning in development mode:

if (firstChild && firstChild.getAttribute('role') === 'presentation') {
  if (firstChild.id) {
    section.setAttribute('aria-labelledby', firstChild.id)
  } else {
    console.warn('Prima Dropdown: Section heading missing required id attribute')
  }
}

4. ID Uniqueness

Issue: No validation exists to catch duplicate IDs within a dropdown. Duplicate IDs would cause ARIA relationship issues.

Recommendation: Consider adding development-mode validation to warn about duplicate IDs (lower priority, can be future enhancement).

🔍 Code Quality

Positive

  • Clean removal of complexity from JavaScript
  • Consistent attribute patterns across all components
  • Good separation of concerns
  • All fixture files properly updated

Minor Observations

  • The test in dropdown_sections_test.exs:36-48 now checks for specific IDs which is good, but makes tests more brittle if ID naming conventions change
  • Consider documenting ID naming conventions (e.g., {parent-id}-{component}-{index})

🎯 Performance & Security

Performance: ✅ Improved - Removing ID generation reduces initialization overhead

Security: ✅ No concerns - Actually reduces attack surface by removing dynamic generation

📋 Final Verdict

Conditional Approval - This is solid work with good architectural decisions. The code quality is high and tests are comprehensive.

Required before merge:

  1. Document this as a breaking change in CHANGELOG
  2. Add migration guide or prominent note in release documentation

Recommended (can be follow-up):

  1. Document the Enum.with_index/1 pattern for dynamic lists
  2. Add development-mode warning for missing heading IDs
  3. Document ID naming conventions

Test Verification Needed:

Can you confirm all tests pass? I'd like to verify the Wallaby browser tests work correctly with the new explicit ID requirements.


Great work simplifying the architecture while maintaining accessibility! The main concern is ensuring users understand the breaking nature of this change.

@ukutaht ukutaht merged commit ae25916 into main Feb 11, 2026
2 checks passed
@ukutaht ukutaht deleted the require-ids-for-dropdown branch February 11, 2026 14:56
@claude
Copy link

claude bot commented Feb 11, 2026

Pull Request Review

This PR simplifies the dropdown component's ID management by requiring explicit IDs rather than auto-generating them. Overall, this is a positive change that improves API clarity and removes unnecessary complexity.

✅ Strengths

1. Simplified Architecture

  • Removes 25 lines of auto-ID generation logic from JavaScript
  • Makes the component API more explicit and predictable
  • Reduces client-side complexity by moving ID management to the server side

2. Improved Developer Experience

  • Developers now have full control over component IDs
  • No more debugging auto-generated IDs like dropdown-item-0
  • Better testability with stable, meaningful IDs

3. Better Accessibility

  • ARIA relationships (aria-controls, aria-labelledby) are now more transparent
  • Section headings must have explicit IDs, making the relationship to their sections clearer

4. Consistent with Best Practices

  • Follows Phoenix Component conventions where important elements should have explicit IDs
  • Aligns with how LiveView typically handles component identification

🔍 Code Quality Observations

JavaScript Simplification (assets/js/hooks/dropdown.js)

  • Removed setupMenuitemIds() function entirely - clean deletion
  • Simplified setupAriaRelationships() to assume IDs exist
  • Simplified setupSectionLabels() to remove ID auto-generation

Elixir Changes (lib/prima/dropdown.ex)

  • Added required: true to id attribute for:
    • dropdown (was previously defaulted to empty string)
    • dropdown_trigger (new requirement)
    • dropdown_menu (new requirement)
    • dropdown_item (new requirement)
    • dropdown_heading (already required, documentation updated)
  • Documentation properly updated to reflect new requirements

⚠️ Considerations

1. Breaking Change
This is a breaking change for existing users who relied on auto-generated IDs. Consider:

  • Bumping the minor or major version number
  • Adding a migration guide in the changelog
  • Documenting this prominently in release notes

2. Documentation Examples
All code examples have been updated consistently, which is excellent. The pattern used is sensible:

<.dropdown_item 
  :for={{option, index} <- Enum.with_index(options)}
  id="{base_id}-item-#{index}"
>

3. Test Coverage
The test changes look good:

  • dropdown_sections_test.exs now checks for specific heading IDs
  • Tests verify the ARIA relationships work correctly
  • The fixture files all have explicit IDs

🐛 Potential Issues

None identified. The implementation looks solid and the changes are internally consistent.

📝 Minor Suggestions

1. Error Messages
When IDs are missing (since they're required), Phoenix will show a compile-time error. Consider if the error message is clear enough for developers. You might want to add a custom validation or clearer documentation about the ID requirement.

2. Documentation
The documentation is good, but consider adding a brief note in dropdown_section docs about needing IDs on headings:

# Section with heading (heading ID required for ARIA relationship)
<.dropdown_section>
  <.dropdown_heading id="account-heading">Account</.dropdown_heading>
  ...
</.dropdown_section>

✅ Recommendation

Approve with minor documentation enhancement suggested.

This is a well-executed refactoring that:

  • Simplifies the codebase
  • Improves clarity and predictability
  • Maintains full accessibility
  • Includes comprehensive test coverage
  • Updates all examples consistently

The breaking change is justified by the improved developer experience and reduced complexity.


Commits:

  • Require IDs for dropdown_section - Clear, descriptive
  • Mix format - Good hygiene
  • Mix format in demo/ folder - Good hygiene

Great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant