Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions ee/apps/den-web/app/(den)/_components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type DenInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "disable
* Consistent text input for all dashboard pages, based on the
* Shared Workspaces compact search field.
*
* Defaults: rounded-lg · py-2.5 · px-4 · text-[14px]
* Defaults: rounded-lg · h-[42px] · px-4 · text-[14px]/leading-5
* Icon: auto-positions and adjusts left padding.
* No className needed at the call site — override only when necessary.
*/
Expand Down Expand Up @@ -56,7 +56,7 @@ export function DenInput({
className={[
// base visual style
"w-full rounded-lg border border-gray-200 bg-white",
"py-2.5 px-4 text-[14px] text-gray-900",
"h-[42px] px-4 text-[14px] leading-5 text-gray-900",
"outline-none transition-all placeholder:text-gray-400",
"focus:border-gray-300 focus:ring-2 focus:ring-gray-900/5",
// disabled state
Expand Down
57 changes: 57 additions & 0 deletions ee/apps/den-web/app/(den)/_components/ui/select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";

import { ChevronDown } from "lucide-react";
import type { SelectHTMLAttributes } from "react";

export type DenSelectProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, "disabled"> & {
/**
* Disables the select and dims it to 60 % opacity.
* Forwarded as the native `disabled` attribute.
*/
disabled?: boolean;
};

/**
* DenSelect
*
* Consistent native select for all dashboard pages, matched to the
* Shared Workspaces compact field sizing used by DenInput.
*
* Defaults: rounded-lg · h-[42px] · px-4/pr-10 · text-[14px]/leading-5
* Chevron: custom Lucide chevron replaces browser-native control chrome.
* No className needed at the call site - override only when necessary.
*/
export function DenSelect({
disabled = false,
className,
children,
...rest
}: DenSelectProps) {
return (
<div className="relative">
<select
{...rest}
disabled={disabled}
className={[
"w-full appearance-none rounded-lg border border-gray-200 bg-white",
"h-[42px] px-4 pr-10 text-[14px] leading-5 text-gray-900",
"outline-none transition-all",
"focus:border-gray-300 focus:ring-2 focus:ring-gray-900/5",
disabled ? "cursor-not-allowed opacity-60" : "",
className ?? "",
]
.filter(Boolean)
.join(" ")}
>
{children}
</select>
<div className="pointer-events-none absolute inset-y-0 right-3 flex items-center">
<ChevronDown
size={16}
className={disabled ? "text-gray-300" : "text-gray-400"}
aria-hidden="true"
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { UnderlineTabs } from "../../../../_components/ui/tabs";
import { DashboardPageTemplate } from "../../../../_components/ui/dashboard-page-template";
import { DenButton } from "../../../../_components/ui/button";
import { DenInput } from "../../../../_components/ui/input";
import { DenSelect } from "../../../../_components/ui/select";

type MembersTab = "members" | "teams" | "roles" | "invitations";

Expand Down Expand Up @@ -283,17 +284,13 @@ export function ManageMembersScreen() {
</label>
<label className="grid gap-3">
<span className="text-[14px] font-medium text-gray-700">Role</span>
<select
value={inviteRole}
onChange={(event) => setInviteRole(event.target.value)}
className="h-14 rounded-[20px] border border-gray-200 bg-[#f8fafc] px-4 text-[15px] text-gray-900 outline-none transition focus:border-gray-300 focus:ring-4 focus:ring-gray-900/5"
>
<DenSelect value={inviteRole} onChange={(event) => setInviteRole(event.target.value)}>
{assignableRoles.map((role) => (
<option key={role.id} value={role.role}>
{formatRoleLabel(role.role)}
</option>
))}
</select>
</DenSelect>
</label>
<div className="flex gap-2 lg:justify-end">
<ActionButton onClick={resetInviteForm}>Cancel</ActionButton>
Expand Down Expand Up @@ -327,17 +324,13 @@ export function ManageMembersScreen() {
>
<label className="grid gap-3">
<span className="text-[14px] font-medium text-gray-700">Role</span>
<select
value={memberRoleDraft}
onChange={(event) => setMemberRoleDraft(event.target.value)}
className="h-14 rounded-[20px] border border-gray-200 bg-[#f8fafc] px-4 text-[15px] text-gray-900 outline-none transition focus:border-gray-300 focus:ring-4 focus:ring-gray-900/5"
>
<DenSelect value={memberRoleDraft} onChange={(event) => setMemberRoleDraft(event.target.value)}>
{assignableRoles.map((role) => (
<option key={role.id} value={role.role}>
{formatRoleLabel(role.role)}
</option>
))}
</select>
</DenSelect>
</label>
<div className="flex gap-2 lg:justify-end">
<ActionButton onClick={resetMemberEditor}>Cancel</ActionButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
import { ArrowLeft, Upload } from "lucide-react";
import { DenButton } from "../../../../_components/ui/button";
import { DenInput } from "../../../../_components/ui/input";
import { DenSelect } from "../../../../_components/ui/select";
import { DenTextarea } from "../../../../_components/ui/textarea";
import { getErrorMessage, requestJson } from "../../../../_lib/den-flow";
import {
Expand Down Expand Up @@ -238,15 +239,14 @@ export function SkillEditorScreen({ skillId }: { skillId?: string }) {

<label className="grid gap-2">
<span className="text-[13px] font-medium text-gray-600">Visibility</span>
<select
<DenSelect
value={visibility}
onChange={(event) => setVisibility(event.target.value as SkillVisibility)}
className="w-full rounded-lg border border-gray-200 bg-white px-4 py-2.5 text-[14px] text-gray-900 outline-none transition-all focus:border-gray-300 focus:ring-2 focus:ring-gray-900/5"
>
<option value="private">Private</option>
<option value="org">Org</option>
<option value="public">Public</option>
</select>
</DenSelect>
</label>

<label className="grid gap-2">
Expand Down