From 23c59c48f369c8d5f422d125c913b20296db9bda Mon Sep 17 00:00:00 2001 From: Ilya Topilskii Date: Wed, 4 Dec 2024 16:06:23 +0100 Subject: [PATCH] refactor: migrate form components to a new structure and update imports - Renamed and exported ButtonGroup as a standalone component. - Removed deprecated FormErrorMessage and FormLegend components. - Introduced new form components: Caption, Checkbox, ControlGroup, Fieldset, Input, Label, Legend, Message, Option, Radio, Select, Separator, Textarea. - Updated imports across various components to use the new form structure. - Adjusted styling and class names for consistency. - Refactored error handling to utilize the new Message component. --- packages/ui/src/components/button-group.tsx | 10 ++- .../src/components/filters/filter-trigger.tsx | 2 +- .../filters-bar/filter-variants/calendar.tsx | 2 +- .../filters-bar/filter-variants/checkbox.tsx | 2 +- .../filters-bar/filter-variants/number.tsx | 2 +- .../filters-bar/filter-variants/text.tsx | 2 +- .../components/filters/filters-bar/sorts.tsx | 2 +- .../ui/src/components/form-error-message.tsx | 37 --------- packages/ui/src/components/form-legend.tsx | 24 ------ packages/ui/src/components/form/caption.tsx | 25 ++++++ .../ui/src/components/{ => form}/checkbox.tsx | 24 +++--- .../components/{ => form}/control-group.tsx | 9 +++ .../ui/src/components/{ => form}/fieldset.tsx | 10 +++ packages/ui/src/components/form/index.ts | 13 ++++ .../ui/src/components/{ => form}/input.tsx | 60 ++++++++++----- .../ui/src/components/{ => form}/label.tsx | 23 ++++-- packages/ui/src/components/form/legend.tsx | 42 ++++++++++ packages/ui/src/components/form/message.tsx | 66 ++++++++++++++++ packages/ui/src/components/form/option.tsx | 65 ++++++++++++++++ packages/ui/src/components/form/radio.tsx | 47 +++++++++++ .../ui/src/components/{ => form}/select.tsx | 60 +++++++++++---- .../separator.tsx} | 15 ++++ .../ui/src/components/{ => form}/textarea.tsx | 40 ++++++---- packages/ui/src/components/index.ts | 14 +--- .../components/manage-navigation/index.tsx | 16 ++-- packages/ui/src/components/radio-group.tsx | 77 ------------------- .../pull-request-compare-button.tsx | 4 +- .../components/pull-request-compare-form.tsx | 8 +- .../ui/src/views/repo/repo-create/index.tsx | 56 +++++++------- .../ui/src/views/repo/repo-sidebar/index.tsx | 8 +- .../views/repo/repo-summary/repo-summary.tsx | 8 +- .../views/src/components/form-field-set.tsx | 2 +- 32 files changed, 497 insertions(+), 278 deletions(-) delete mode 100644 packages/ui/src/components/form-error-message.tsx delete mode 100644 packages/ui/src/components/form-legend.tsx create mode 100644 packages/ui/src/components/form/caption.tsx rename packages/ui/src/components/{ => form}/checkbox.tsx (65%) rename packages/ui/src/components/{ => form}/control-group.tsx (54%) rename packages/ui/src/components/{ => form}/fieldset.tsx (50%) create mode 100644 packages/ui/src/components/form/index.ts rename packages/ui/src/components/{ => form}/input.tsx (51%) rename packages/ui/src/components/{ => form}/label.tsx (60%) create mode 100644 packages/ui/src/components/form/legend.tsx create mode 100644 packages/ui/src/components/form/message.tsx create mode 100644 packages/ui/src/components/form/option.tsx create mode 100644 packages/ui/src/components/form/radio.tsx rename packages/ui/src/components/{ => form}/select.tsx (71%) rename packages/ui/src/components/{form-separator.tsx => form/separator.tsx} (52%) rename packages/ui/src/components/{ => form}/textarea.tsx (53%) delete mode 100644 packages/ui/src/components/radio-group.tsx diff --git a/packages/ui/src/components/button-group.tsx b/packages/ui/src/components/button-group.tsx index b5d4b70ed5..dffe1edda9 100644 --- a/packages/ui/src/components/button-group.tsx +++ b/packages/ui/src/components/button-group.tsx @@ -10,7 +10,13 @@ interface ButtonGroupProps { verticalAlign?: string } -function Root({ children, direction = 'horizontal', className, spacing = '4', verticalAlign }: ButtonGroupProps) { +export function ButtonGroup({ + children, + direction = 'horizontal', + className, + spacing = '4', + verticalAlign +}: ButtonGroupProps) { const gapClass = `gap-${spacing}` const verticalAlignClass = verticalAlign ? `items-${verticalAlign}` : '' @@ -20,5 +26,3 @@ function Root({ children, direction = 'horizontal', className, spacing = '4', ve ) } - -export { Root } diff --git a/packages/ui/src/components/filters/filter-trigger.tsx b/packages/ui/src/components/filters/filter-trigger.tsx index eb6d84b756..3a83d83600 100644 --- a/packages/ui/src/components/filters/filter-trigger.tsx +++ b/packages/ui/src/components/filters/filter-trigger.tsx @@ -1,6 +1,6 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@components/dropdown-menu' +import { Input } from '@components/form' import { Icon } from '@components/icon' -import { Input } from '@components/input' import { TFunction } from 'i18next' import { FilterOption, SortOption } from './types' diff --git a/packages/ui/src/components/filters/filters-bar/filter-variants/calendar.tsx b/packages/ui/src/components/filters/filters-bar/filter-variants/calendar.tsx index 790b6b29b1..432027cc13 100644 --- a/packages/ui/src/components/filters/filters-bar/filter-variants/calendar.tsx +++ b/packages/ui/src/components/filters/filters-bar/filter-variants/calendar.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Calendar as UICalendar, type CalendarDateRange } from '@components/calendar' -import { Input } from '@components/input' +import { Input } from '@components/form' import { cn } from '@utils/cn' import { FilterValue } from '../../types' diff --git a/packages/ui/src/components/filters/filters-bar/filter-variants/checkbox.tsx b/packages/ui/src/components/filters/filters-bar/filter-variants/checkbox.tsx index 8b5050ba94..0b3cb9be89 100644 --- a/packages/ui/src/components/filters/filters-bar/filter-variants/checkbox.tsx +++ b/packages/ui/src/components/filters/filters-bar/filter-variants/checkbox.tsx @@ -1,6 +1,6 @@ import { DropdownMenuCheckboxItem } from '@components/dropdown-menu' +import { Input } from '@components/form' import { Icon } from '@components/icon' -import { Input } from '@components/input' import { CheckboxFilterOption, FilterValue } from '../../types' import { UseFiltersReturn } from '../../use-filters' diff --git a/packages/ui/src/components/filters/filters-bar/filter-variants/number.tsx b/packages/ui/src/components/filters/filters-bar/filter-variants/number.tsx index 85a21bed29..9a7ba013c1 100644 --- a/packages/ui/src/components/filters/filters-bar/filter-variants/number.tsx +++ b/packages/ui/src/components/filters/filters-bar/filter-variants/number.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' +import { Input } from '@components/form' import { Icon } from '@components/icon' -import { Input } from '@components/input' import { FilterValue } from '../../types' import { UseFiltersReturn } from '../../use-filters' diff --git a/packages/ui/src/components/filters/filters-bar/filter-variants/text.tsx b/packages/ui/src/components/filters/filters-bar/filter-variants/text.tsx index e877f2f642..0b7a0d14cc 100644 --- a/packages/ui/src/components/filters/filters-bar/filter-variants/text.tsx +++ b/packages/ui/src/components/filters/filters-bar/filter-variants/text.tsx @@ -1,8 +1,8 @@ import { useState } from 'react' import { DropdownMenuItem } from '@components/dropdown-menu' +import { Input } from '@components/form' import { Icon } from '@components/icon' -import { Input } from '@components/input' import { FilterValue } from '../../types' import { UseFiltersReturn } from '../../use-filters' diff --git a/packages/ui/src/components/filters/filters-bar/sorts.tsx b/packages/ui/src/components/filters/filters-bar/sorts.tsx index 7c1092054e..45400ce162 100644 --- a/packages/ui/src/components/filters/filters-bar/sorts.tsx +++ b/packages/ui/src/components/filters/filters-bar/sorts.tsx @@ -1,8 +1,8 @@ import { useEffect, useState } from 'react' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@components/dropdown-menu' +import { Input } from '@components/form' import { Icon } from '@components/icon' -import { Input } from '@components/input' import { closestCenter, DndContext } from '@dnd-kit/core' import { SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' diff --git a/packages/ui/src/components/form-error-message.tsx b/packages/ui/src/components/form-error-message.tsx deleted file mode 100644 index a76f89c1ed..0000000000 --- a/packages/ui/src/components/form-error-message.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { HTMLAttributes } from 'react' - -import { cn } from '@utils/cn' - -import { Text } from './text' - -export enum ErrorMessageTheme { - SUCCESS = 'success', - WARNING = 'warning', - ERROR = 'error', - DEFAULT = 'default' -} - -interface FormErrorMessageProps extends HTMLAttributes { - theme: ErrorMessageTheme -} - -const themeClassMap: Record = { - [ErrorMessageTheme.SUCCESS]: 'text-success', - [ErrorMessageTheme.WARNING]: 'text-warning', - [ErrorMessageTheme.ERROR]: 'text-foreground-danger', - [ErrorMessageTheme.DEFAULT]: 'text-tertiary-background' -} - -export function FormErrorMessage({ children, theme, className }: FormErrorMessageProps) { - const textClass = themeClassMap[theme] - const role = theme === ErrorMessageTheme.ERROR ? 'alert' : 'status' - const ariaLive = theme === ErrorMessageTheme.ERROR ? 'assertive' : 'polite' - - return ( -
- - {children} - -
- ) -} diff --git a/packages/ui/src/components/form-legend.tsx b/packages/ui/src/components/form-legend.tsx deleted file mode 100644 index 9deaccd370..0000000000 --- a/packages/ui/src/components/form-legend.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { ReactNode } from 'react' - -import { Text } from '@components/text' - -interface FormLegendProps { - title: ReactNode - description?: ReactNode - className?: string -} - -export function FormLegend({ title, description, className }: FormLegendProps) { - return ( -
- - {title} - - {description && ( - - {description} - - )} -
- ) -} diff --git a/packages/ui/src/components/form/caption.tsx b/packages/ui/src/components/form/caption.tsx new file mode 100644 index 0000000000..5e3ab9f72c --- /dev/null +++ b/packages/ui/src/components/form/caption.tsx @@ -0,0 +1,25 @@ +import { PropsWithChildren } from 'react' + +import { Text } from '@/components' +import { cn } from '@utils/cn' + +interface CaptionProps extends PropsWithChildren { + className?: string +} + +/** + * Caption component that renders supplementary text below form inputs. + * Used to provide additional context or hints for form fields. + * + * @param {CaptionProps} props - The properties for the Caption component. + * @param {React.ReactNode} props.children - The content to be displayed as the caption text. + * @param {string} [props.className] - Optional additional class names for styling. + * @returns {JSX.Element} The rendered Caption component. + */ +export function Caption({ children, className }: CaptionProps) { + return ( + + {children} + + ) +} diff --git a/packages/ui/src/components/checkbox.tsx b/packages/ui/src/components/form/checkbox.tsx similarity index 65% rename from packages/ui/src/components/checkbox.tsx rename to packages/ui/src/components/form/checkbox.tsx index 513aef78e3..ff7b233b80 100644 --- a/packages/ui/src/components/checkbox.tsx +++ b/packages/ui/src/components/form/checkbox.tsx @@ -1,17 +1,22 @@ import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react' +import { Icon } from '@/components' import * as CheckboxPrimitive from '@radix-ui/react-checkbox' import { cn } from '@utils/cn' -import { Icon } from './icon' -import { Label } from './label' - -interface CheckboxProps extends ComponentPropsWithoutRef { - label?: string -} +interface CheckboxProps extends ComponentPropsWithoutRef {} +/** + * Checkbox component that provides a customizable, accessible checkbox input. + * Built on top of Radix UI Checkbox primitive with additional styling. + * + * @param {CheckboxProps} props - The properties for the Checkbox component. + * @param {string} [props.className] - Optional additional class names for styling. + * @param {React.Ref} ref - Forward ref for the checkbox element. + * @returns {JSX.Element} The rendered Checkbox component. + */ const Checkbox = forwardRef, CheckboxProps>( - ({ className, label, ...props }, ref) => ( + ({ className, ...props }, ref) => (
, CheckboxP - {label && ( - - )}
) ) diff --git a/packages/ui/src/components/control-group.tsx b/packages/ui/src/components/form/control-group.tsx similarity index 54% rename from packages/ui/src/components/control-group.tsx rename to packages/ui/src/components/form/control-group.tsx index f06ed08215..13eec5d94a 100644 --- a/packages/ui/src/components/control-group.tsx +++ b/packages/ui/src/components/form/control-group.tsx @@ -6,6 +6,15 @@ interface ControlGroupProps extends HTMLAttributes { type?: 'button' | 'input' } +/** + * A container component that groups form control elements together. + * + * @param props.type - Specifies the type of control group ('button' or 'input'). + * Affects spacing and ARIA labels. + * @param props.children - The form control elements to be grouped (Label, Input/Button, + * ErrorMessage, Caption, etc.). + * @param props.className - Additional CSS classes to apply to the control group. + */ export function ControlGroup({ children, type, className, ...props }: ControlGroupProps) { return (
{ shaded?: boolean } +/** + * A form fieldset component that groups related form elements. + * @component + * @param {FieldsetProps} props - The component props + * @param {ReactNode} props.children - The content to be rendered inside the fieldset + * @param {boolean} [props.box] - When true, adds border and padding to create a box around the fieldset + * @param {boolean} [props.shaded] - When true, adds a subtle background color to the fieldset + * @param {string} [props.className] - Additional CSS classes to apply to the fieldset + * @returns {JSX.Element} A styled fieldset element + */ export function Fieldset({ children, box, shaded, className, ...props }: FieldsetProps) { return (
, 'size'>, VariantProps {} @@ -20,8 +16,8 @@ const inputVariants = cva('bg-transparent px-2.5 py-1 text-foreground-1 disabled extended: 'grow border-none focus-visible:outline-none' }, size: { - 32: 'h-8', - 36: 'h-9' + sm: 'h-8', + md: 'h-9' }, theme: { default: @@ -32,7 +28,7 @@ const inputVariants = cva('bg-transparent px-2.5 py-1 text-foreground-1 disabled defaultVariants: { variant: 'default', theme: 'default', - size: 32 + size: 'sm' } }) @@ -45,7 +41,7 @@ const BaseInput = forwardRef( BaseInput.displayName = 'BaseInput' interface InputError { - theme: ErrorMessageTheme + theme: MessageTheme message?: string } @@ -56,27 +52,49 @@ interface InputProps extends BaseInputProps { optional?: boolean } +/** + * A form input component with support for labels, captions, and error messages. + * + * @component + * @param {Object} props - The component props + * @param {string} [props.label] - Optional label text displayed above the input + * @param {ReactNode} [props.caption] - Optional caption text displayed below the input + * @param {InputError} [props.error] - Error configuration object containing theme and message + * @param {string} [props.id] - Input element ID, used for label association + * @param {MessageTheme} [props.theme] - Visual theme of the input + * @param {boolean} [props.disabled] - Whether the input is disabled + * @param {boolean} [props.optional] - Indicates if the field is optional, displays "(Optional)" in the label + * @param {BaseInputProps} props.rest - All other props are passed to the underlying input element + * + * @example + * + */ const Input = forwardRef( ({ label, caption, error, id, theme, disabled, optional, ...props }, ref) => { + const InputWrapper = error || caption || label ? ControlGroup : Fragment + return ( - + {label && ( - + {caption && {caption}} + ) } ) diff --git a/packages/ui/src/components/label.tsx b/packages/ui/src/components/form/label.tsx similarity index 60% rename from packages/ui/src/components/label.tsx rename to packages/ui/src/components/form/label.tsx index 3468b43dfb..ad6ed97ae6 100644 --- a/packages/ui/src/components/label.tsx +++ b/packages/ui/src/components/form/label.tsx @@ -12,15 +12,15 @@ const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacit default: 'text-sm font-normal leading-none' }, color: { - 'foreground-1': 'text-foreground-1', - 'foreground-2': 'text-foreground-2', - 'foreground-5': 'text-foreground-5', - 'foreground-9': 'text-foreground-9' + primary: 'text-foreground-1', + secondary: 'text-foreground-2', + disabled: 'text-foreground-5', + 'disabled-dark': 'text-foreground-9' } }, defaultVariants: { variant: 'default', - color: 'foreground-1' + color: 'primary' } }) @@ -38,6 +38,19 @@ interface LabelProps extends VariantProps, PropsWithChildr className?: string } +/** + * A Label component that wraps the Radix UI LabelPrimitive.Root component. + * It supports variant and color styling through class-variance-authority. + * + * @param {Object} props - The properties object. + * @param {string} [props.htmlFor] - The id of the element this label is associated with. + * @param {boolean} [props.optional] - If true, renders "(optional)" next to the label text. + * @param {string} [props.color] - The color variant of the label. + * @param {string} [props.variant] - The style variant of the label. + * @param {React.ReactNode} props.children - The content of the label. + * @param {string} [props.className] - Additional class names to apply to the label. + * @returns {JSX.Element} The rendered label component. + */ const Label = ({ htmlFor, optional, color, variant, children, className }: LabelProps) => { return ( diff --git a/packages/ui/src/components/form/legend.tsx b/packages/ui/src/components/form/legend.tsx new file mode 100644 index 0000000000..0ab55c2157 --- /dev/null +++ b/packages/ui/src/components/form/legend.tsx @@ -0,0 +1,42 @@ +import { ReactNode } from 'react' + +import { Text } from '@components/text' + +interface LegendProps { + title: ReactNode + description?: ReactNode + className?: string +} + +/** + * Legend component for form fieldsets + * + * @component + * @example + * ```tsx + * + * ``` + * + * @param {object} props - Component props + * @param {ReactNode} props.title - The main title text or element + * @param {ReactNode} [props.description] - Optional description text or element + * @param {string} [props.className] - Optional CSS class name for custom styling + * @returns {JSX.Element} A legend component with title and optional description + */ +export function Legend({ title, description, className }: LegendProps) { + return ( +
+ + {title} + + {description && ( + + {description} + + )} +
+ ) +} diff --git a/packages/ui/src/components/form/message.tsx b/packages/ui/src/components/form/message.tsx new file mode 100644 index 0000000000..b54e4c33eb --- /dev/null +++ b/packages/ui/src/components/form/message.tsx @@ -0,0 +1,66 @@ +import { HTMLAttributes } from 'react' + +import { Text } from '@/components' +import { cn } from '@utils/cn' + +export enum MessageTheme { + SUCCESS = 'success', + WARNING = 'warning', + ERROR = 'error', + DEFAULT = 'default' +} + +interface MessageProps extends HTMLAttributes { + theme: MessageTheme +} + +const themeClassMap: Record = { + [MessageTheme.SUCCESS]: 'text-success', + [MessageTheme.WARNING]: 'text-warning', + [MessageTheme.ERROR]: 'text-foreground-danger', + [MessageTheme.DEFAULT]: 'text-tertiary-background' +} + +/** + * Message component for displaying status or error messages with different themes. + * + * This component is typically used in forms to provide feedback to users, such as success, warning, or error messages. + * + * @component + * @param {MessageProps} props - The properties for the Message component. + * @param {MessageTheme} props.theme - The visual theme of the message (success, warning, error, or default). + * This also affects accessibility attributes. + * @param {React.ReactNode} props.children - The content of the message to display. + * @param {string} [props.className] - Additional CSS classes to apply to the message container. + * + * @returns {JSX.Element} The rendered Message component. + * + * @example + * ```tsx + * + * This field is required + * + * + * + * Changes saved successfully + * + * ``` + * + * @remarks + * - Uses appropriate ARIA roles ('alert' for errors, 'status' for other themes). + * - Sets aria-live appropriately ('assertive' for errors, 'polite' for other themes). + * - Applies theme-specific text colors through Tailwind classes. + */ +export function Message({ children, theme, className }: MessageProps) { + const textClass = themeClassMap[theme] + const role = theme === MessageTheme.ERROR ? 'alert' : 'status' + const ariaLive = theme === MessageTheme.ERROR ? 'assertive' : 'polite' + + return ( +
+ + {children} + +
+ ) +} diff --git a/packages/ui/src/components/form/option.tsx b/packages/ui/src/components/form/option.tsx new file mode 100644 index 0000000000..f49a72ae9f --- /dev/null +++ b/packages/ui/src/components/form/option.tsx @@ -0,0 +1,65 @@ +import { FC, ReactElement, ReactNode } from 'react' + +import { Checkbox, Label, RadioButton, Text } from '@/components' +import { cn } from '@utils/cn' + +type ControlType = ReactElement | ReactElement + +/** + * Interface for Option component props + */ +interface OptionProps { + /** The radio button or checkbox control element */ + control: ControlType + /** Unique identifier for the input */ + id: string + /** Label text for the input */ + label?: string + /** Optional description text or node below the label */ + description?: string | ReactNode + /** Additional CSS classes */ + className?: string + /** Indicates if the item is currently selected */ + ariaSelected?: boolean +} + +/** + * Individual item that contains a control (radio button or checkbox) with optional label and description + * @component + * @example + *
diff --git a/packages/ui/src/views/repo/repo-create/index.tsx b/packages/ui/src/views/repo/repo-create/index.tsx index 010a9cc053..a2621fa800 100644 --- a/packages/ui/src/views/repo/repo-create/index.tsx +++ b/packages/ui/src/views/repo/repo-create/index.tsx @@ -6,13 +6,13 @@ import { ButtonGroup, Checkbox, ControlGroup, - ErrorMessageTheme, Fieldset, - FormErrorMessage, Input, + Message, + MessageTheme, + Option, RadioButton, RadioGroup, - RadioGroupItem, Select, SelectContent, SelectItem, @@ -113,7 +113,7 @@ export function RepoCreatePage({ Create a new repository - + A repository contains all project files, including the revision history. Already have a project repository elsewhere?{' '} @@ -129,8 +129,8 @@ export function RepoCreatePage({ label="Name" {...register('name')} placeholder="Enter repository name" - size={36} - error={errors.name && { theme: ErrorMessageTheme.ERROR, message: errors.name.message?.toString() }} + size="md" + error={errors.name && { theme: MessageTheme.ERROR, message: errors.name.message?.toString() }} autoFocus /> @@ -142,7 +142,7 @@ export function RepoCreatePage({ label="Description" error={ errors.description && { - theme: ErrorMessageTheme.ERROR, + theme: MessageTheme.ERROR, message: errors.description.message?.toString() } } @@ -162,7 +162,7 @@ export function RepoCreatePage({ label="Add a .gitignore" error={ errors.gitignore && { - theme: ErrorMessageTheme.ERROR, + theme: MessageTheme.ERROR, message: errors.gitignore.message?.toString() } } @@ -192,7 +192,7 @@ export function RepoCreatePage({ label="Choose a license" error={ errors.license && { - theme: ErrorMessageTheme.ERROR, + theme: MessageTheme.ERROR, message: errors.license.message?.toString() } } @@ -214,18 +214,18 @@ export function RepoCreatePage({ {/* ACCESS */}
- + Who has access - } id="access-public" label="Public" ariaSelected={accessValue === '1'} description="Anyone with access to the Gitness environment can clone this repo." /> - } id="access-private" label="Private" @@ -234,9 +234,9 @@ export function RepoCreatePage({ /> {errors.access && ( - + {errors.access.message?.toString()} - + )}
@@ -245,10 +245,10 @@ export function RepoCreatePage({ {/* README */}
- + Initialize this repository with - } id="readme" @@ -264,26 +264,22 @@ export function RepoCreatePage({ } /> - {errors.readme && ( - {errors.readme.message?.toString()} - )} + {errors.readme && {errors.readme.message?.toString()}}
{/* SUBMIT BUTTONS */}
- - <> - {/* TODO: Improve loading state to avoid flickering */} - - - - + + {/* TODO: Improve loading state to avoid flickering */} + + +
diff --git a/packages/ui/src/views/repo/repo-sidebar/index.tsx b/packages/ui/src/views/repo/repo-sidebar/index.tsx index adede730ed..e36ab2c1e5 100644 --- a/packages/ui/src/views/repo/repo-sidebar/index.tsx +++ b/packages/ui/src/views/repo/repo-sidebar/index.tsx @@ -54,9 +54,9 @@ export const RepoSidebar = ({ useTranslationStore={useTranslationStore} /> )} - + - +
- + - + - +