diff --git a/apps/design-system/src/pages/view-preview/view-settings.tsx b/apps/design-system/src/pages/view-preview/view-settings.tsx index bc3738ee70..2e79f16b16 100644 --- a/apps/design-system/src/pages/view-preview/view-settings.tsx +++ b/apps/design-system/src/pages/view-preview/view-settings.tsx @@ -3,7 +3,7 @@ import { useLocation, useNavigate } from 'react-router-dom' import { clsx } from 'clsx' -import { Button, Icon, Select, SelectContent, SelectItem, Spacer } from '@harnessio/ui/components' +import { Button, Icon, Select, Spacer } from '@harnessio/ui/components' import css from './view-settings.module.css' @@ -17,7 +17,7 @@ enum Themes { DARK_PROT_STD = 'dark-prot-std', DARK_STANDARD_HIGH = 'dark-std-high', LIGHT = 'light-std-std', - LIGHT_PROTO_STD = 'light-prot-std' + LIGHT_PROT_STD = 'light-prot-std' } const ViewSettings: FC = ({ routes }) => { @@ -65,30 +65,30 @@ const ViewSettings: FC = ({ routes }) => { {showSettings && ( <> - + + - + + )} diff --git a/apps/portal/src/content/docs/components/select.mdx b/apps/portal/src/content/docs/components/select.mdx new file mode 100644 index 0000000000..9c58432678 --- /dev/null +++ b/apps/portal/src/content/docs/components/select.mdx @@ -0,0 +1,378 @@ +--- +title: Select +description: Select component +--- + +The `Select` component provides a way to create dropdown selections with various sub-components for customization. + +import { DocsPage } from "../../../components/docs-page"; + + { + const [color, setColor] = React.useState() + const [randomItem, setRandomItem] = React.useState() + const [searchRandomItems, setSearchRandomItems] = React.useState('') + + const allRandomItems = React.useMemo( + () => [...new Array(300)].map((_, index) => ({value: index+1, label: \`Item \${index+1}\`})), + [] + ) + + const filteredRandomItems = React.useMemo( + () => searchRandomItems.trim() ? allRandomItems.filter(item => item.label.toLowerCase().includes(searchRandomItems.toLowerCase())) : allRandomItems, + ) + + return ( +
+
+
With group
+ + + Standard + Accessible + Vivid + + + + + Custom label + Custom + + + +
+ +
+ +
+
With search
+ + + {filteredRandomItems.map(item => ( + + {item.label} + + ))} + + +
+
+ ) + +}`} +/> + +## Usage + +```typescript jsx +import { Select } from '@harnessio/ui/components' + +//... + +const [color, setColor] = useState() + +return ( + + + Standard + Accessible + Vivid + + + + + Custom label + Custom + + + +) +``` + +## Anatomy + +All parts of the `Select` component can be imported and composed as required. + +```typescript jsx + + + + + + + + + + +``` + +## API Reference + +### `Root` + +The `Root` component for the Select can be either controlled or uncontrolled. A controlled Select component takes a `value` +and an `onValueChange` handler as props, and will only update the value when the user makes a selection. An uncontrolled +Select component will update the value whenever a user makes a selection, and will not re-render when the value is +changed from outside the component. + +```typescript jsx + + {/* Select content */} + +``` + + void", + }, + ]} +/> + +### `Content` + +The content of the select dropdown. This is a required element. The `defaultValue` prop sets the default value of the +select. The `withSearch` prop enables search support in the dropdown. This is optional and can be used to search the +available options. The `searchProps` prop is used to pass additional props to the search input when `withSearch` is +true. This can be used to customize the search input, such as changing the placeholder text. + +```typescript jsx + + {/* SelectItem components */} + +``` + + void }", + }, + ]} +/> + +### `Item` + +The `Item` component is used to create an individual item in the select dropdown. Each item requires a `value` prop +which is the value of the item. If the value is not suitable for typeahead search, you can use the `textValue` prop to +provide a searchable text string for typeahead search. For example, if the value is JSON-encoded object, `textValue` can +be used to provide a searchable label for the object. + +```typescript jsx + + Name + +``` + + + +### `Separator` + +The `Separator` component is used to create a separator in the select dropdown. + +```typescript jsx + +``` + + + +### `Group` + +The `Group` component is used to create a group of items in the select dropdown. + +```typescript jsx + + Custom label + Custom + +``` + + + +### `Label` + +The `Label` component is used to create a label for a group of items in the select dropdown. + +```typescript jsx + + Custom label + +``` + + diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index a2e61f7d19..17dea81556 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,4 +1,13 @@ -import { Children, ComponentPropsWithoutRef, ElementRef, FC, forwardRef, PropsWithChildren, ReactNode } from 'react' +import { + Children, + ComponentPropsWithoutRef, + ElementRef, + FC, + forwardRef, + HTMLAttributes, + PropsWithChildren, + ReactNode +} from 'react' import { Caption, Icon, Label, Message, MessageTheme, SearchBox } from '@/components' import { usePortal } from '@/context' @@ -6,8 +15,8 @@ import { useDebounceSearch } from '@hooks/use-debounce-search' import * as SelectPrimitive from '@radix-ui/react-select' import { cn } from '@utils/cn' -interface SelectProps - extends Omit>, 'defaultValue'>, 'dir'>, +interface SelectRootProps + extends Omit>, 'defaultValue'>, 'dir'>, SelectPrimitive.SelectProps { label?: string error?: string @@ -20,12 +29,14 @@ interface SelectProps /** * A customizable select component that supports labels, error states, and captions * @example - * + * + * + * Option 1 + * Option 2 + * + * */ -const Select: FC = ({ +const SelectRoot: FC = ({ name, label, error, @@ -60,7 +71,7 @@ const Select: FC = ({ {caption && {caption}} ) -Select.displayName = SelectPrimitive.Root.displayName +SelectRoot.displayName = SelectPrimitive.Root.displayName const SelectGroup = SelectPrimitive.Group @@ -209,4 +220,13 @@ const SelectSeparator = forwardRef< )) SelectSeparator.displayName = SelectPrimitive.Separator.displayName -export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator } +const Select = { + Root: SelectRoot, + Group: SelectGroup, + Content: SelectContent, + Label: SelectLabel, + Item: SelectItem, + Separator: SelectSeparator +} + +export { Select } diff --git a/packages/ui/src/components/theme-selector-v2/theme-dialog.tsx b/packages/ui/src/components/theme-selector-v2/theme-dialog.tsx index f1b1308bba..fcabce90cd 100644 --- a/packages/ui/src/components/theme-selector-v2/theme-dialog.tsx +++ b/packages/ui/src/components/theme-selector-v2/theme-dialog.tsx @@ -1,6 +1,6 @@ import { FC, useEffect, useState } from 'react' -import { Dialog, Icon, Select, SelectContent, SelectItem, Separator } from '@/components' +import { Dialog, Icon, Select, Separator } from '@/components' import darkModeImage from '@/svgs/theme-dark.png' import lightModeImage from '@/svgs/theme-light.png' import { cn } from '@/utils/cn' @@ -95,7 +95,7 @@ const ThemeDialog: FC = ({ defaultTheme, theme, open, onOpenCh High contrast improves readability, Dimmer mode reduces glare.

- + + @@ -124,7 +124,7 @@ const ThemeDialog: FC = ({ defaultTheme, theme, open, onOpenCh Adjust colors for different types of color blindness.

- + + diff --git a/packages/ui/src/components/theme-selector/color-select.tsx b/packages/ui/src/components/theme-selector/color-select.tsx index 42fbcf125b..3f02efabfe 100644 --- a/packages/ui/src/components/theme-selector/color-select.tsx +++ b/packages/ui/src/components/theme-selector/color-select.tsx @@ -1,4 +1,5 @@ -import { Label, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator } from '..' +import { Label, Select } from '@/components' + import { ColorType, ContrastType, FullTheme, ModeType } from './types' export function ColorSelect({ @@ -15,7 +16,7 @@ export function ColorSelect({ return (
- + + Standard + + + Vision Assistive + Tritanopia + Protanopia & Deuteranopia + + +
) } diff --git a/packages/ui/src/components/theme-selector/contrast-select.tsx b/packages/ui/src/components/theme-selector/contrast-select.tsx index 8ee5236439..628dcaffa8 100644 --- a/packages/ui/src/components/theme-selector/contrast-select.tsx +++ b/packages/ui/src/components/theme-selector/contrast-select.tsx @@ -1,4 +1,5 @@ -import { Label, Select, SelectContent, SelectItem } from '..' +import { Label, Select } from '@/components' + import { ColorType, ContrastType, FullTheme, ModeType } from './types' export function ContrastSelect({ @@ -15,7 +16,7 @@ export function ContrastSelect({ return (
- + + Standard + Low + High + +
) } diff --git a/packages/ui/src/components/theme-selector/mode-select.tsx b/packages/ui/src/components/theme-selector/mode-select.tsx index 25e830f087..7454488990 100644 --- a/packages/ui/src/components/theme-selector/mode-select.tsx +++ b/packages/ui/src/components/theme-selector/mode-select.tsx @@ -1,4 +1,5 @@ -import { Label, Select, SelectContent, SelectItem } from '..' +import { Label, Select } from '@/components' + import { ColorType, ContrastType, FullTheme, ModeType } from './types' export function ModeSelect({ @@ -15,7 +16,7 @@ export function ModeSelect({ return (
- + + Light + Dark + System + +
) } diff --git a/packages/ui/src/views/labels/components/label-form-color-and-name-group.tsx b/packages/ui/src/views/labels/components/label-form-color-and-name-group.tsx index 6bb83d4ca3..369f12d7ee 100644 --- a/packages/ui/src/views/labels/components/label-form-color-and-name-group.tsx +++ b/packages/ui/src/views/labels/components/label-form-color-and-name-group.tsx @@ -1,7 +1,7 @@ import { FC } from 'react' import { UseFormRegister } from 'react-hook-form' -import { Button, Icon, Input, Select, SelectContent, SelectItem } from '@/components' +import { Button, Icon, Input, Select } from '@/components' import { ColorsEnum, CreateLabelFormFields, TranslationStore } from '@/views' const SelectColorMarker = { @@ -50,18 +50,18 @@ export const LabelFormColorAndNameGroup: FC = ( return (
- + +
= (props:
Branch: - + +
) : null} diff --git a/packages/ui/src/views/pipelines/create-pipeline-dialog/create-pipeline-dialog.tsx b/packages/ui/src/views/pipelines/create-pipeline-dialog/create-pipeline-dialog.tsx index a4ba326946..e9aa15ee3e 100644 --- a/packages/ui/src/views/pipelines/create-pipeline-dialog/create-pipeline-dialog.tsx +++ b/packages/ui/src/views/pipelines/create-pipeline-dialog/create-pipeline-dialog.tsx @@ -1,18 +1,7 @@ import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' -import { - Alert, - Button, - ControlGroup, - Dialog, - Fieldset, - FormWrapper, - Input, - Select, - SelectContent, - SelectItem -} from '@/components' +import { Alert, Button, ControlGroup, Dialog, Fieldset, FormWrapper, Input, Select } from '@/components' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' @@ -116,7 +105,7 @@ export function CreatePipelineDialog(props: CreatePipelineDialogProps) {
- + +
diff --git a/packages/ui/src/views/profile-settings/components/profile-settings-token-create-dialog.tsx b/packages/ui/src/views/profile-settings/components/profile-settings-token-create-dialog.tsx index 2238023a16..86a49839cb 100644 --- a/packages/ui/src/views/profile-settings/components/profile-settings-token-create-dialog.tsx +++ b/packages/ui/src/views/profile-settings/components/profile-settings-token-create-dialog.tsx @@ -1,18 +1,7 @@ import { FC, useEffect } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' -import { - Alert, - Button, - CopyButton, - Dialog, - Fieldset, - FormWrapper, - Input, - Select, - SelectContent, - SelectItem -} from '@/components' +import { Alert, Button, CopyButton, Dialog, Fieldset, FormWrapper, Input, Select } from '@/components' import { zodResolver } from '@hookform/resolvers/zod' import { TranslationStore } from '@views/repo' import { z } from 'zod' @@ -170,23 +159,23 @@ export const ProfileSettingsTokenCreateDialog: FC
- + + {isValid && ( {watch('lifetime') === 'never' ? ( diff --git a/packages/ui/src/views/project/project-import.tsx b/packages/ui/src/views/project/project-import.tsx index 335e2e14a6..f5879fac32 100644 --- a/packages/ui/src/views/project/project-import.tsx +++ b/packages/ui/src/views/project/project-import.tsx @@ -12,8 +12,6 @@ import { Input, Option, Select, - SelectContent, - SelectItem, Spacer, Text } from '@/components' @@ -104,18 +102,18 @@ export function ImportProjectPage({ onFormSubmit, onFormCancel, isLoading, apiEr {/* provider */}
- + +
{watch('provider') === ProviderOptionsEnum.GITHUB_ENTERPRISE && ( diff --git a/packages/ui/src/views/project/project-members/components/invite-member-dialog.tsx b/packages/ui/src/views/project/project-members/components/invite-member-dialog.tsx index 8299ea5cad..19eb8c3890 100644 --- a/packages/ui/src/views/project/project-members/components/invite-member-dialog.tsx +++ b/packages/ui/src/views/project/project-members/components/invite-member-dialog.tsx @@ -1,18 +1,7 @@ import { FC, forwardRef, useEffect, useMemo, useState } from 'react' import { useForm } from 'react-hook-form' -import { - Alert, - Avatar, - Button, - ControlGroup, - Dialog, - Fieldset, - FormWrapper, - Select, - SelectContent, - SelectItem -} from '@/components' +import { Alert, Avatar, Button, ControlGroup, Dialog, Fieldset, FormWrapper, Select } from '@/components' import { PrincipalType } from '@/types' import { InviteMemberDialogProps, InviteMemberFormFields } from '@/views' import { zodResolver } from '@hookform/resolvers/zod' @@ -122,7 +111,7 @@ export const InviteMemberDialog: FC = ({
- + + - + +
diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-status-select-button.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-status-select-button.tsx index db738b0a63..459e499487 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-status-select-button.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-status-select-button.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useState } from 'react' -import { Select, SelectContent, SelectItem } from '@components/index' +import { Select } from '@/components' import { useEmitCodeCommentStatus } from '@views/repo/pull-request/hooks/useEmitCodeCommentStatus' import { TypesPullReq } from '@views/repo/pull-request/pull-request.types' @@ -19,12 +19,12 @@ interface StatusButtonProps { } const StatusButton = ({ codeCommentStatus, onChange }: StatusButtonProps) => ( - + + + Active + Resolved + + ) StatusButton.displayName = 'StatusButton' diff --git a/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx b/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx index 652d2d4b75..e0a56cfb19 100644 --- a/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx +++ b/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx @@ -1,19 +1,7 @@ import { useEffect, useMemo } from 'react' import { useForm } from 'react-hook-form' -import { - Alert, - Button, - ControlGroup, - Dialog, - Fieldset, - FormWrapper, - Icon, - Input, - Select, - SelectContent, - SelectItem -} from '@/components' +import { Alert, Button, ControlGroup, Dialog, Fieldset, FormWrapper, Icon, Input, Select } from '@/components' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' @@ -118,7 +106,7 @@ export function CreateBranchDialog({
- + +
diff --git a/packages/ui/src/views/repo/repo-create/index.tsx b/packages/ui/src/views/repo/repo-create/index.tsx index e1536a8a54..4d5f8f3956 100644 --- a/packages/ui/src/views/repo/repo-create/index.tsx +++ b/packages/ui/src/views/repo/repo-create/index.tsx @@ -15,8 +15,6 @@ import { RadioButton, RadioGroup, Select, - SelectContent, - SelectItem, Spacer, StyledLink, Text, @@ -154,7 +152,7 @@ export function RepoCreatePage({ {/* GITIGNORE */}
- + + {/* LICENSE */} - + +
diff --git a/packages/ui/src/views/repo/repo-import/repo-import-mulitple.tsx b/packages/ui/src/views/repo/repo-import/repo-import-mulitple.tsx index da709acd11..fc3a70aabb 100644 --- a/packages/ui/src/views/repo/repo-import/repo-import-mulitple.tsx +++ b/packages/ui/src/views/repo/repo-import/repo-import-mulitple.tsx @@ -11,8 +11,6 @@ import { Input, Option, Select, - SelectContent, - SelectItem, Spacer, Text } from '@/components' @@ -163,24 +161,24 @@ export function RepoImportMultiplePage({ {/* provider */}
- + +
diff --git a/packages/ui/src/views/repo/repo-import/repo-import.tsx b/packages/ui/src/views/repo/repo-import/repo-import.tsx index 192c0c99c0..fd00daae1e 100644 --- a/packages/ui/src/views/repo/repo-import/repo-import.tsx +++ b/packages/ui/src/views/repo/repo-import/repo-import.tsx @@ -12,8 +12,6 @@ import { Input, Option, Select, - SelectContent, - SelectItem, Spacer, Text, Textarea @@ -163,24 +161,24 @@ export function RepoImportPage({ {/* provider */}
- + +