diff --git a/apps/eclipse/content/design-system/components/meta.json b/apps/eclipse/content/design-system/components/meta.json
index 0e5e59c8b5..5d0d142b60 100644
--- a/apps/eclipse/content/design-system/components/meta.json
+++ b/apps/eclipse/content/design-system/components/meta.json
@@ -26,6 +26,7 @@
"pagination",
"radio-group",
"separator",
+ "select",
"slider",
"spinner",
"statistic",
diff --git a/apps/eclipse/content/design-system/components/select.mdx b/apps/eclipse/content/design-system/components/select.mdx
new file mode 100644
index 0000000000..94b560fb57
--- /dev/null
+++ b/apps/eclipse/content/design-system/components/select.mdx
@@ -0,0 +1,714 @@
+---
+title: Select
+description: A select component for choosing a value from a list of options. Features keyboard navigation, grouped options, custom positioning, and full accessibility support.
+---
+
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+ Field,
+ FieldLabel,
+ FieldDescription,
+ FieldError,
+} from "@prisma/eclipse";
+
+### Usage
+
+**Basic Select**
+
+A simple select with options:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function BasicSelect() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+**Grouped Options**
+
+Organize options into labeled groups:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function GroupedSelect() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+**Small Size**
+
+Use the `sm` size for compact layouts:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function SmallSelect() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+**Disabled State**
+
+Disable the select when interaction should be prevented:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function DisabledSelect() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+**With Field Component**
+
+Use with Field for proper form structure:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+ Field,
+ FieldLabel,
+ FieldDescription,
+} from "@prisma/eclipse";
+
+export function SelectWithField() {
+ return (
+
+ Country
+
+ Choose your country of residence.
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+ Country
+
+ Choose your country of residence.
+
+
+
+**Position Control**
+
+Control the position and alignment of the dropdown:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function PositionedSelect() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+**Disabled Items**
+
+Disable individual items:
+
+```tsx
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function SelectWithDisabledItems() {
+ return (
+
+ );
+}
+```
+
+**Live Example:**
+
+
+
Live Example:
+
+
+
+### API Reference
+
+#### Select
+
+The root component that manages select state.
+
+**Props:**
+- `value` - Controlled value (string, optional)
+- `onValueChange` - Callback when value changes ((value: string) => void, optional)
+- `open` - Controlled open state (boolean, optional)
+- `onOpenChange` - Callback when open state changes ((open: boolean) => void, optional)
+- `disabled` - Disable the select (boolean, default: false)
+- `defaultValue` - Default value for uncontrolled mode (string, optional)
+- `defaultOpen` - Default open state (boolean, default: false)
+- `name` - Form input name (string, optional)
+- `required` - Mark as required (boolean, default: false)
+
+```tsx
+
+```
+
+#### SelectTrigger
+
+The button that triggers the select dropdown.
+
+**Props:**
+- `size` - Size variant ("sm" | "default", default: "default")
+- `className` - Additional CSS classes (string or function, optional)
+- `disabled` - Disable the trigger (boolean, default: false)
+- All standard HTML button attributes
+
+```tsx
+
+
+
+```
+
+#### SelectValue
+
+Displays the currently selected value or placeholder.
+
+**Props:**
+- `placeholder` - Text to show when no value is selected (string, optional)
+- `className` - Additional CSS classes (string or function, optional)
+
+```tsx
+
+```
+
+#### SelectContent
+
+The dropdown container that holds the list of options.
+
+**Props:**
+- `side` - Position relative to trigger ("top" | "bottom" | "left" | "right", default: "bottom")
+- `align` - Alignment relative to trigger ("start" | "center" | "end", default: "center")
+- `sideOffset` - Distance from trigger in pixels (number, default: 4)
+- `alignOffset` - Alignment offset in pixels (number, default: 0)
+- `alignItemWithTrigger` - Align selected item with trigger (boolean, default: true)
+- `className` - Additional CSS classes (string or function, optional)
+
+```tsx
+
+ {/* SelectItem components */}
+
+```
+
+#### SelectItem
+
+An individual option in the select list.
+
+**Props:**
+- `value` - The value of the item (string, required)
+- `disabled` - Disable the item (boolean, default: false)
+- `className` - Additional CSS classes (string or function, optional)
+- `children` - Item content (ReactNode)
+
+```tsx
+Option 1
+Disabled Option
+```
+
+#### SelectGroup
+
+A container for grouping related items.
+
+**Props:**
+- `className` - Additional CSS classes (string or function, optional)
+- `children` - Group content (ReactNode)
+
+```tsx
+
+ Category
+ Item 1
+
+```
+
+#### SelectLabel
+
+A label for a group of items.
+
+**Props:**
+- `className` - Additional CSS classes (string or function, optional)
+- `children` - Label content (ReactNode)
+
+```tsx
+Frontend Languages
+```
+
+#### SelectSeparator
+
+A visual separator between groups or items.
+
+**Props:**
+- `className` - Additional CSS classes (string or function, optional)
+
+```tsx
+
+```
+
+#### SelectScrollUpButton
+
+Internal component for scrolling up in long lists. Automatically rendered.
+
+#### SelectScrollDownButton
+
+Internal component for scrolling down in long lists. Automatically rendered.
+
+### Features
+
+- ✅ Two size variants (default and small)
+- ✅ Keyboard navigation (Arrow keys, Enter, Escape, Tab, Home, End)
+- ✅ Grouped options with labels
+- ✅ Custom positioning and alignment
+- ✅ Disabled state for select and individual items
+- ✅ Controlled and uncontrolled modes
+- ✅ Scroll buttons for long lists
+- ✅ Item indicator with checkmark
+- ✅ Accessible with ARIA attributes
+- ✅ Portal rendering for z-index management
+- ✅ Animations for open/close transitions
+- ✅ Auto-alignment of selected item with trigger
+- ✅ Form integration with name and required attributes
+- ✅ Fully typed with TypeScript
+
+### Best Practices
+
+- Always provide a placeholder for better UX
+- Use SelectGroup and SelectLabel for organized lists
+- Consider using the small size in dense layouts
+- Disable items that are temporarily unavailable rather than hiding them
+- Keep option text concise and scannable
+- Use Field component for proper form structure with labels
+- Test keyboard navigation thoroughly
+- Avoid extremely long lists (consider search/filter for 50+ items)
+- Use consistent option formatting
+- Provide clear value descriptions
+
+### Accessibility
+
+The Select component follows ARIA combobox pattern specifications:
+
+- Uses semantic ARIA roles (`combobox`, `listbox`, `option`)
+- Supports full keyboard navigation:
+ - `Space/Enter` - Open/close and select
+ - `Arrow Down/Up` - Navigate through options
+ - `Home/End` - Jump to first/last option
+ - `Escape` - Close the dropdown
+ - `Tab` - Move focus and close dropdown
+- Focus management and trapped focus in dropdown
+- Screen reader announcements for selections and state changes
+- Proper labeling with `aria-label` and `aria-labelledby`
+- Visual focus indicators
+- Selected state announced to assistive technologies
+- Disabled items are properly marked and unfocusable
+- Required attribute for form validation
+
+### Common Use Cases
+
+The Select component is perfect for:
+
+- **Form inputs** - Collecting user choices in forms
+- **Settings** - Configuration and preference selection
+- **Filters** - Filtering data by category
+- **Language/locale switchers** - Selecting language or region
+- **Status updates** - Changing item status
+- **Priority selection** - Setting task or issue priority
+- **Category selection** - Choosing from predefined categories
+- **Time zones** - Selecting time zone
+- **Country/region pickers** - Location selection
+- **Sorting options** - Choosing sort order
+- **Role assignment** - Selecting user roles
+
+### Styling
+
+The Select component uses design tokens and can be customized:
+
+- **Trigger**: Border, rounded corners, padding, hover/focus states
+- **Content**: Popover with shadow, rounded corners, animations
+- **Items**: Hover/focus states with accent colors
+- **Selected indicator**: Checkmark icon aligned right
+- **Groups**: Scroll margin and padding
+- **Labels**: Muted text, small font size
+- **Separator**: Border line between groups
+- **Scroll buttons**: Positioned at top/bottom with icons
+
+Customize by passing `className` props:
+
+```tsx
+
+```
+
+### Integration with Forms
+
+Use with form libraries like React Hook Form:
+
+```tsx
+import { useForm, Controller } from "react-hook-form";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@prisma/eclipse";
+
+export function SelectForm() {
+ const { control, handleSubmit } = useForm();
+
+ return (
+
+ );
+}
+```
+
+### Controlled vs Uncontrolled
+
+**Uncontrolled (with defaultValue):**
+```tsx
+
+```
+
+**Controlled (with value and onValueChange):**
+```tsx
+const [value, setValue] = useState("option1");
+
+
+```
+
+### Performance Tips
+
+For large option lists:
+
+1. **Virtualization** - Consider using virtual scrolling for 100+ items
+2. **Lazy loading** - Load options on-demand
+3. **Memoization** - Use React.memo for SelectItem components
+4. **Search/filter** - Add search for easier navigation
+5. **Pagination** - Load options in batches
+
+```tsx
+import { useMemo } from "react";
+
+export function OptimizedSelect({ items }) {
+ const memoizedItems = useMemo(
+ () => items.map((item) => (
+
+ {item.name}
+
+ )),
+ [items]
+ );
+
+ return (
+
+ );
+}
+```
diff --git a/packages/eclipse/package.json b/packages/eclipse/package.json
index fdeef469cd..3ca42b7ae5 100644
--- a/packages/eclipse/package.json
+++ b/packages/eclipse/package.json
@@ -38,7 +38,7 @@
"scripts": {
"build": "rimraf dist && pnpm run build:ts && pnpm run build:styles",
"build:ts": "tsdown --config tsdown.config.ts",
- "build:styles": "mkdir -p dist/styles dist/static/fonts && cp ./src/styles/globals.css ./dist/styles/globals.css && cp ./src/styles/fonts.css ./dist/styles/fonts.css && cp ./src/styles/steps.css ./dist/styles/steps.css && cp ./src/static/fonts/* ./dist/static/fonts/",
+ "build:styles": "mkdir -p dist/styles dist/static/fonts && cp ./src/styles/globals.css ./dist/styles/globals.css && cp ./src/styles/fonts.css ./dist/styles/fonts.css && cp ./src/styles/steps.css ./dist/styles/steps.css && cp -r ./src/static/fonts/. ./dist/static/fonts/",
"check": "oxfmt . --write && oxlint . --fix",
"types:check": "tsc --noEmit",
"prepublishOnly": "pnpm run build && pnpm run types:check"
diff --git a/packages/eclipse/src/components/index.ts b/packages/eclipse/src/components/index.ts
index c882be9f09..fa034f917b 100644
--- a/packages/eclipse/src/components/index.ts
+++ b/packages/eclipse/src/components/index.ts
@@ -157,6 +157,19 @@ export {
export { Alert } from "./alert";
export { Switch } from "./switch";
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+} from "./select";
+
export {
Empty,
EmptyHeader,
diff --git a/packages/eclipse/src/components/select.tsx b/packages/eclipse/src/components/select.tsx
new file mode 100644
index 0000000000..8c2da48d57
--- /dev/null
+++ b/packages/eclipse/src/components/select.tsx
@@ -0,0 +1,214 @@
+"use client";
+
+import * as React from "react";
+import { Select as SelectPrimitive } from "@base-ui/react/select";
+
+import { cn } from "../lib/cn";
+
+// Helper to handle className that can be a string or function
+function handleClassName(
+ className: string | ((state: T) => string | undefined) | undefined,
+ staticClasses: string,
+): string | ((state: T) => string | undefined) {
+ if (typeof className === "function") {
+ return (state: T) => cn(staticClasses, className(state));
+ }
+ return cn(staticClasses, className);
+}
+
+const Select = SelectPrimitive.Root;
+
+function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {
+ return (
+
+ );
+}
+
+function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
+ return (
+
+ );
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: SelectPrimitive.Trigger.Props & {
+ size?: "sm" | "default";
+}) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function SelectContent({
+ className,
+ children,
+ side = "bottom",
+ sideOffset = 4,
+ align = "start",
+ alignOffset = 0,
+ alignItemWithTrigger = false,
+ ...props
+}: SelectPrimitive.Popup.Props &
+ Pick<
+ SelectPrimitive.Positioner.Props,
+ "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
+ >) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function SelectLabel({
+ className,
+ ...props
+}: SelectPrimitive.GroupLabel.Props) {
+ return (
+
+ );
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: SelectPrimitive.Item.Props) {
+ return (
+
+
+ {children}
+
+
+
+
+ }
+ />
+
+ );
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: SelectPrimitive.Separator.Props) {
+ return (
+
+ );
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ );
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ );
+}
+
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+};