Skip to content

FE-822: Add Select to ds#8842

Open
alex-e-leon wants to merge 41 commits into
mainfrom
FE-822-add-select-to-ds
Open

FE-822: Add Select to ds#8842
alex-e-leon wants to merge 41 commits into
mainfrom
FE-822-add-select-to-ds

Conversation

@alex-e-leon

Copy link
Copy Markdown
Contributor

🌟 What is the purpose of this PR?

Adds a Select component to the design system

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jun 8, 2026 5:47pm
hashdotdesign-tokens Ready Ready Preview, Comment Jun 8, 2026 5:47pm
petrinaut Ready Ready Preview, Comment Jun 8, 2026 5:47pm

@cursor

cursor Bot commented Jun 8, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Introduces a new public Select API and tightens SelectableList item typing (optional id, removed selectedStyle "none"), which could break rare consumers; TextInput width/connector styling changes may affect visual parity.

Overview
Adds a new Select component to @hashintel/ds-components (Ark UI select + shared form-input styling), with Ladle stories covering variants, sizes, widths, connected inputs, clearable/required typing, and custom item renderers.

The dropdown reuses SelectableList via as="Select" (item groups, tick selection, empty/loading states). SelectableList item IDs can be inferred from string text through getItemId, and selectedStyle: "none" is removed (highlight already renders no indicator).

Shared form recipes are aligned for Select and TextInput: --base-input-connector-width moves into formSizes, width tokens apply on the wrapper, and SharedInputProps.inputRef widens to React.Ref<Element>. Minor list/menu styling and story layout tweaks accompany the change.

Reviewed by Cursor Bugbot for commit 1d75f91. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps > hash.design Affects the `hash.design` design site (app) labels Jun 8, 2026
Comment thread libs/@hashintel/ds-components/src/components/Select/select.tsx
);
}

return <ItemRow key={entry.id} item={entry} ctx={ctx} />;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Menu group keys omit id

Low Severity

Grouped menu rows still use child.id as the React key while sibling rendering uses getItemId(child). For items that omit id but use string text, keys become undefined, which can cause duplicate-key warnings and unstable list updates even though menu values use getItemId.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 753ff53. Configure here.

emptyState ??
(loading ? "Loading options…" : "No options available")
}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Select dropdown loading spinner missing

Medium Severity

When loading is true and items is empty, the list panel shows the emptyState text (e.g. “Loading options…”) instead of SelectableList’s loading UI, because loading is never passed through to SelectableList even though the trigger shows a spinner.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fe5a92a. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 5 total unresolved issues (including 3 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1d75f91. Configure here.

const next = nextValue[0];
if (next === NONE_VALUE) {
(onChange as (value: null) => void)(null);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dropdown clear skips onClear

Medium Severity

Choosing the optional empty list entry calls onChange(null) only, while the clear button invokes clearable.onClear(). Side effects tied to onClear (analytics, resetting related state) do not run when the user clears via the dropdown.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d75f91. Configure here.

createListCollection<Item>({
items: flattenItems(menuItems),
itemToValue: (item) => getItemId(item),
itemToString: (item) => getItemId(item),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Typeahead uses value not label

Medium Severity

createListCollection sets itemToString to getItemId(item) (the option value), not the visible label from SelectItem.text or rendered item text. Keyboard typeahead and related string matching follow the raw value when label and value differ.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d75f91. Configure here.

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

Labels

area/apps > hash.design Affects the `hash.design` design site (app) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

1 participant