mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2026-07-27 08:51:22 +08:00
[questions][ui] last minute ui changes
This commit is contained in:
@@ -56,7 +56,7 @@ export default function QuestionAggregateBadge({
|
|||||||
<button
|
<button
|
||||||
ref={setTriggerRef}
|
ref={setTriggerRef}
|
||||||
className="-my-1 flex items-center rounded-md px-2
|
className="-my-1 flex items-center rounded-md px-2
|
||||||
py-1 text-xs font-medium text-slate-500 hover:bg-slate-100 hover:text-slate-600"
|
py-1 text-xs font-medium text-slate-500 bg-slate-100 hover:bg-slate-200 hover:text-slate-600"
|
||||||
type="button">
|
type="button">
|
||||||
<Icon
|
<Icon
|
||||||
aria-hidden={true}
|
aria-hidden={true}
|
||||||
|
|||||||
29
apps/portal/src/components/questions/QuestionContainer.tsx
Normal file
29
apps/portal/src/components/questions/QuestionContainer.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// TODO: Remove this after Steps
|
||||||
|
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type Props = Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
variant?: 'md' | 'sm' | 'xs';
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function QuestionContainer({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
variant = 'md',
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'mx-auto px-4 sm:px-6 lg:px-8',
|
||||||
|
variant === 'md' && 'max-w-7xl',
|
||||||
|
variant === 'sm' && 'max-w-7xl',
|
||||||
|
variant === 'xs' && 'max-w-3xl',
|
||||||
|
className,
|
||||||
|
)}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
AdjustmentsHorizontalIcon,
|
AdjustmentsHorizontalIcon,
|
||||||
MagnifyingGlassIcon,
|
MagnifyingGlassIcon,
|
||||||
} from '@heroicons/react/24/outline';
|
} from '@heroicons/react/24/outline';
|
||||||
import { Button, DropdownMenu, TextInput } from '@tih/ui';
|
import { Button, Tabs, TextInput } from '@tih/ui';
|
||||||
|
|
||||||
import { SORT_ORDERS } from '~/utils/questions/constants';
|
import { SORT_ORDERS } from '~/utils/questions/constants';
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ export default function QuestionSearchBar({
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex flex-col items-stretch gap-x-2 gap-y-4 lg:flex-row lg:items-end">
|
<div className="flex flex-col items-stretch gap-x-2 gap-y-4 lg:flex-row lg:items-end">
|
||||||
<div className="flex flex-1 items-center gap-4">
|
<div className="flex flex-1 gap-2">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<TextInput
|
<TextInput
|
||||||
isLabelHidden={true}
|
isLabelHidden={true}
|
||||||
@@ -57,48 +57,52 @@ export default function QuestionSearchBar({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu align="end" label="Sort by">
|
|
||||||
{(sortOptionsSelectProps.sortTypeOptions ?? []).map(
|
|
||||||
({ value: sortTypeValue }) =>
|
|
||||||
(sortOptionsSelectProps?.sortOrderOptions ?? SORT_ORDERS).map(
|
|
||||||
({ value: sortOrderValue }) => (
|
|
||||||
<DropdownMenu.Item
|
|
||||||
key={`${sortTypeValue}/${sortOrderValue}`}
|
|
||||||
isSelected={
|
|
||||||
sortOptionsSelectProps.sortTypeValue ===
|
|
||||||
sortTypeValue &&
|
|
||||||
sortOptionsSelectProps.sortOrderValue === sortOrderValue
|
|
||||||
}
|
|
||||||
label={getSortOrderLabel(sortOrderValue, sortTypeValue)}
|
|
||||||
onClick={() => {
|
|
||||||
sortOptionsSelectProps.onSortTypeChange?.(
|
|
||||||
sortTypeValue,
|
|
||||||
);
|
|
||||||
sortOptionsSelectProps.onSortOrderChange?.(
|
|
||||||
sortOrderValue,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</DropdownMenu>
|
|
||||||
<div className="lg:hidden">
|
<div className="lg:hidden">
|
||||||
<Button
|
<Button
|
||||||
addonPosition="start"
|
addonPosition="start"
|
||||||
aria-label={
|
icon={AdjustmentsHorizontalIcon}
|
||||||
|
label={
|
||||||
activeFilterCount > 0
|
activeFilterCount > 0
|
||||||
? `Filters (${activeFilterCount})`
|
? `Filters (${activeFilterCount})`
|
||||||
: 'Filters'
|
: 'Filters'
|
||||||
}
|
}
|
||||||
icon={AdjustmentsHorizontalIcon}
|
|
||||||
label={`(${activeFilterCount})`}
|
|
||||||
variant={activeFilterCount > 0 ? 'secondary' : 'tertiary'}
|
variant={activeFilterCount > 0 ? 'secondary' : 'tertiary'}
|
||||||
onClick={onFilterOptionsToggle}
|
onClick={onFilterOptionsToggle}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col justify-start gap-x-4 gap-y-2 sm:flex-row">
|
||||||
|
<div>
|
||||||
|
<Tabs
|
||||||
|
label="Sort by"
|
||||||
|
tabs={sortOptionsSelectProps.sortTypeOptions ?? []}
|
||||||
|
value={sortOptionsSelectProps.sortTypeValue}
|
||||||
|
onChange={sortOptionsSelectProps.onSortTypeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="border-b border-l" />
|
||||||
|
<div>
|
||||||
|
<Tabs
|
||||||
|
label="Order by"
|
||||||
|
tabs={(sortOptionsSelectProps.sortOrderOptions ?? SORT_ORDERS).map(
|
||||||
|
(option) => {
|
||||||
|
const newLabel = getSortOrderLabel(
|
||||||
|
option.value,
|
||||||
|
sortOptionsSelectProps.sortTypeValue,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
label: newLabel,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
value={sortOptionsSelectProps.sortOrderValue}
|
||||||
|
onChange={sortOptionsSelectProps.onSortOrderChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ export default function VotingButtons({
|
|||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<button
|
<button
|
||||||
aria-label="Upvote"
|
aria-label="Upvote"
|
||||||
className="rounded-full p-1 hover:bg-slate-100"
|
className={clsx(
|
||||||
|
'rounded-full p-1 hover:bg-slate-100',
|
||||||
|
vote?.vote === 'UPVOTE' && 'bg-primary-50',
|
||||||
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -50,7 +53,7 @@ export default function VotingButtons({
|
|||||||
<ChevronUpIcon
|
<ChevronUpIcon
|
||||||
className={clsx(
|
className={clsx(
|
||||||
size === 'sm' && 'h-5 w-5',
|
size === 'sm' && 'h-5 w-5',
|
||||||
size === 'md' && 'h-8 w-8',
|
size === 'md' && 'h-6 w-6',
|
||||||
vote?.vote === 'UPVOTE'
|
vote?.vote === 'UPVOTE'
|
||||||
? 'text-primary-500'
|
? 'text-primary-500'
|
||||||
: 'hover:text-primary-500 text-slate-400',
|
: 'hover:text-primary-500 text-slate-400',
|
||||||
@@ -60,7 +63,10 @@ export default function VotingButtons({
|
|||||||
<p>{upvoteCount}</p>
|
<p>{upvoteCount}</p>
|
||||||
<button
|
<button
|
||||||
aria-label="Downvote"
|
aria-label="Downvote"
|
||||||
className="rounded-full p-1 hover:bg-slate-100"
|
className={clsx(
|
||||||
|
'rounded-full p-1 hover:bg-slate-100',
|
||||||
|
vote?.vote === 'DOWNVOTE' && 'bg-danger-50',
|
||||||
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -70,7 +76,7 @@ export default function VotingButtons({
|
|||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
className={clsx(
|
className={clsx(
|
||||||
size === 'sm' && 'h-5 w-5',
|
size === 'sm' && 'h-5 w-5',
|
||||||
size === 'md' && 'h-8 w-8',
|
size === 'md' && 'h-6 w-6',
|
||||||
vote?.vote === 'DOWNVOTE'
|
vote?.vote === 'DOWNVOTE'
|
||||||
? 'text-danger-500'
|
? 'text-danger-500'
|
||||||
: 'hover:text-danger-500 text-slate-400',
|
: 'hover:text-danger-500 text-slate-400',
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ export default function BaseQuestionCard({
|
|||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'whitespace-pre-line text-base font-medium leading-6 text-slate-900 md:text-lg',
|
'md:text-md whitespace-pre-line text-base font-medium leading-6 text-slate-900',
|
||||||
truncateContent && 'line-clamp-2 text-ellipsis',
|
truncateContent && 'line-clamp-2 text-ellipsis',
|
||||||
)}>
|
)}>
|
||||||
{content}
|
{content}
|
||||||
@@ -321,7 +321,7 @@ export default function BaseQuestionCard({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'group flex gap-4 border-slate-200',
|
'group flex gap-4 border-slate-200',
|
||||||
showHover && 'hover:border-primary-500 transition',
|
showHover && 'hover:border-primary-500 transition',
|
||||||
!hideCard && 'rounded-md border bg-white p-4 sm:rounded-lg sm:p-6',
|
!hideCard && 'rounded-md border bg-white px-2 py-4 sm:rounded-lg',
|
||||||
)}>
|
)}>
|
||||||
{cardContent}
|
{cardContent}
|
||||||
{showDeleteButton && (
|
{showDeleteButton && (
|
||||||
|
|||||||
@@ -261,7 +261,6 @@ export default function QuestionPage() {
|
|||||||
/>
|
/>
|
||||||
<div className="sm:ml-13 ml-11 mr-2 md:ml-14">
|
<div className="sm:ml-13 ml-11 mr-2 md:ml-14">
|
||||||
<Collapsible
|
<Collapsible
|
||||||
defaultOpen={true}
|
|
||||||
label={
|
label={
|
||||||
<div className="text-primary-700">
|
<div className="text-primary-700">
|
||||||
{question.numComments}{' '}
|
{question.numComments}{' '}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import QuestionOverviewCard from '~/components/questions/card/question/QuestionO
|
|||||||
import ContributeQuestionCard from '~/components/questions/ContributeQuestionCard';
|
import ContributeQuestionCard from '~/components/questions/ContributeQuestionCard';
|
||||||
import FilterSection from '~/components/questions/filter/FilterSection';
|
import FilterSection from '~/components/questions/filter/FilterSection';
|
||||||
import PaginationLoadMoreButton from '~/components/questions/PaginationLoadMoreButton';
|
import PaginationLoadMoreButton from '~/components/questions/PaginationLoadMoreButton';
|
||||||
|
import QuestionContainer from '~/components/questions/QuestionContainer';
|
||||||
import QuestionSearchBar from '~/components/questions/QuestionSearchBar';
|
import QuestionSearchBar from '~/components/questions/QuestionSearchBar';
|
||||||
import CompanyTypeahead from '~/components/questions/typeahead/CompanyTypeahead';
|
import CompanyTypeahead from '~/components/questions/typeahead/CompanyTypeahead';
|
||||||
import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahead';
|
import LocationTypeahead from '~/components/questions/typeahead/LocationTypeahead';
|
||||||
import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead';
|
import RoleTypeahead from '~/components/questions/typeahead/RoleTypeahead';
|
||||||
import Container from '~/components/shared/Container';
|
|
||||||
import type { JobTitleType } from '~/components/shared/JobTitles';
|
import type { JobTitleType } from '~/components/shared/JobTitles';
|
||||||
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
|
import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
|
||||||
|
|
||||||
@@ -506,7 +506,7 @@ export default function QuestionsBrowsePage() {
|
|||||||
<title>Home - {APP_TITLE}</title>
|
<title>Home - {APP_TITLE}</title>
|
||||||
</Head>
|
</Head>
|
||||||
<main>
|
<main>
|
||||||
<Container className="relative flex" variant="sm">
|
<QuestionContainer className="relative flex" variant="sm">
|
||||||
<section className="min-h-0 flex-1 overflow-auto">
|
<section className="min-h-0 flex-1 overflow-auto">
|
||||||
<div className="my-4 mx-auto flex flex-col items-stretch justify-start gap-6 sm:px-4">
|
<div className="my-4 mx-auto flex flex-col items-stretch justify-start gap-6 sm:px-4">
|
||||||
<ContributeQuestionCard
|
<ContributeQuestionCard
|
||||||
@@ -589,7 +589,7 @@ export default function QuestionsBrowsePage() {
|
|||||||
<h2 className="px-4 text-xl font-semibold">Filter by</h2>
|
<h2 className="px-4 text-xl font-semibold">Filter by</h2>
|
||||||
{filterSidebar}
|
{filterSidebar}
|
||||||
</aside>
|
</aside>
|
||||||
</Container>
|
</QuestionContainer>
|
||||||
<SlideOut
|
<SlideOut
|
||||||
className="lg:hidden"
|
className="lg:hidden"
|
||||||
enterFrom="end"
|
enterFrom="end"
|
||||||
|
|||||||
Reference in New Issue
Block a user