Skip to content

Commit

Permalink
feat: add BaseSelectNative component (#3169)
Browse files Browse the repository at this point in the history
  • Loading branch information
wescopeland authored Feb 5, 2025
1 parent 052faa5 commit 30eb0cb
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 37 deletions.
49 changes: 49 additions & 0 deletions resources/js/common/components/+vendor/BaseSelectNative.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as React from 'react';
import { LuChevronDown } from 'react-icons/lu';

import { cn } from '@/common/utils/cn';

export interface BaseSelectPropsNative extends React.SelectHTMLAttributes<HTMLSelectElement> {
children: React.ReactNode;
}

const BaseSelectNative = React.forwardRef<HTMLSelectElement, BaseSelectPropsNative>(
({ className, children, ...props }, ref) => {
return (
<div className="relative">
<select
className={cn(
'peer inline-flex h-10 w-full cursor-pointer appearance-none items-center rounded-md',
'border border-neutral-800 bg-neutral-950 text-sm text-menu-link',
'focus-visible:border-ring transition-colors focus-visible:outline-none focus-visible:ring-1',
'focus-visible:ring-neutral-300 disabled:pointer-events-none disabled:cursor-not-allowed',
'has-[option[disabled]:checked]:text-muted-foreground disabled:opacity-50',
'light:border-neutral-200 light:bg-white light:focus:ring-neutral-950',

props.multiple
? '[&_option:checked]:bg-accent py-1 [&>*]:px-3 [&>*]:py-1'
: 'h-9 pe-8 ps-3',

className,
)}
ref={ref}
{...props}
>
{children}
</select>
{!props.multiple && (
<span className="text-muted-foreground/80 pointer-events-none absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center peer-disabled:opacity-50">
<LuChevronDown
className="size-4 text-neutral-300 opacity-50 light:text-neutral-800"
strokeWidth={2}
aria-hidden="true"
/>
</span>
)}
</div>
);
},
);
BaseSelectNative.displayName = 'BaseSelectNative';

export { BaseSelectNative };
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ describe('Component: FullPaginator', () => {
);

// ACT
await userEvent.click(screen.getByRole('combobox'));
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(screen.getByRole('combobox'), ['2']);

// ASSERT
expect(onPageSelectValueChange).toHaveBeenCalledWith(2);
Expand Down
42 changes: 19 additions & 23 deletions resources/js/common/components/FullPaginator/FullPaginator.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FC } from 'react';
import { type ChangeEvent, type FC, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { LuArrowLeft, LuArrowLeftToLine, LuArrowRight, LuArrowRightToLine } from 'react-icons/lu';

Expand All @@ -11,13 +11,7 @@ import {
import { cn } from '@/common/utils/cn';

import { baseButtonVariants } from '../+vendor/BaseButton';
import {
BaseSelect,
BaseSelectContent,
BaseSelectItem,
BaseSelectTrigger,
BaseSelectValue,
} from '../+vendor/BaseSelect';
import { BaseSelectNative } from '../+vendor/BaseSelectNative';

interface FullPaginatorProps<TData = unknown> {
onPageSelectValueChange: (newPageValue: number) => void;
Expand All @@ -36,13 +30,20 @@ export const FullPaginator: FC<FullPaginatorProps> = ({
links: { firstPageUrl, lastPageUrl, nextPageUrl, previousPageUrl },
} = paginatedData;

const [internalValue, setInternalValue] = useState(String(currentPage));

if (!previousPageUrl && !nextPageUrl) {
return <span />;
}

// Generate an array of all page numbers. We'll use this to populate the select control.
const pageOptions = Array.from({ length: lastPage }, (_, i) => i + 1);

const handlePageSelect = (event: ChangeEvent<HTMLSelectElement>) => {
setInternalValue(event.target.value);
onPageSelectValueChange(Number(event.target.value));
};

return (
<BasePagination>
<BasePaginationContent>
Expand Down Expand Up @@ -83,22 +84,17 @@ export const FullPaginator: FC<FullPaginatorProps> = ({
>
<span>{t('Page')}</span>

<BaseSelect
value={String(currentPage)}
onValueChange={(value) => onPageSelectValueChange(Number(value))}
<BaseSelectNative
value={internalValue}
onChange={handlePageSelect}
className="!h-[32px] min-w-[70px]"
>
<BaseSelectTrigger className="!h-[32px] min-w-[70px]">
<BaseSelectValue />
</BaseSelectTrigger>

<BaseSelectContent>
{pageOptions.map((page) => (
<BaseSelectItem key={`page-value-${page}`} value={page.toString()}>
{page}
</BaseSelectItem>
))}
</BaseSelectContent>
</BaseSelect>
{pageOptions.map((page) => (
<option key={`page-value-${page}`} value={page.toString()}>
{page}
</option>
))}
</BaseSelectNative>

<span className="whitespace-nowrap">
{t('of {{pageNumber, number}}', { pageNumber: lastPage })}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ describe('Component: AchievementCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ describe('Component: GameClaimsCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe('Component: GameCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ describe('Component: GameHashesCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ describe('Component: GameModificationCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('Component: LeaderboardCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ describe('Component: UserCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describe('Component: UserModerationCommentsMainRoot', () => {
// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ describe('Component: TopAchieversMainRoot', () => {

// ACT
const comboboxEl = screen.getAllByRole('combobox')[0];
await userEvent.click(comboboxEl);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(comboboxEl, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ describe('Component: MessagesRoot', () => {

// ACT
const paginatorCombobox = screen.getAllByRole('combobox')[0];
await userEvent.click(paginatorCombobox);
await userEvent.click(screen.getByRole('option', { name: '2' }));
await userEvent.selectOptions(paginatorCombobox, ['2']);

// ASSERT
expect(visitSpy).toHaveBeenCalledOnce();
Expand Down

0 comments on commit 30eb0cb

Please sign in to comment.