From 3ddf2a963a3208a8c6dcbec3529d479011890bad Mon Sep 17 00:00:00 2001 From: Ray Liu Date: Thu, 19 Dec 2024 14:51:16 +1100 Subject: [PATCH] add dark mode and refactor wfr details page --- eslint.config.js | 13 + package.json | 31 +- prettier.config.js | 3 + src/App.tsx | 15 +- .../common/backdrop/BackdropWithText.tsx | 2 +- src/components/common/badges/StatusBadge.tsx | 9 +- src/components/common/buttons/Button.tsx | 105 +- src/components/common/buttons/IconButton.tsx | 6 +- src/components/common/checkbox/Checkbox.tsx | 6 +- .../common/datepicker/DateRangePicker.tsx | 12 +- .../{ => common}/dialogs/SimpleDialog.tsx | 44 +- src/components/{ => common}/dialogs/index.tsx | 0 src/components/common/drawers/InfoDrawers.tsx | 42 +- src/components/common/drawers/SideDrawer.tsx | 29 +- src/components/common/dropdowns/Dropdown.tsx | 8 +- .../common/dropdowns/IconDropdown.tsx | 6 +- .../common/dropdowns/PopoverDropdown.tsx | 4 +- .../common/error/DetailedErrorBoundary.tsx | 20 +- .../common/json-to-table/json-display.tsx | 45 +- .../common/json-to-table/json-to-list.tsx | 50 +- .../json-to-table/json-to-nested-list.tsx | 56 +- .../common/json-to-table/json-to-table.tsx | 32 +- src/components/common/search/Search.tsx | 33 +- .../common/select/IconMultipleSelect.tsx | 38 +- src/components/common/select/SingleSelect.tsx | 20 +- .../common/spinner/SpinnerWithText.tsx | 2 +- .../common/timelines/HorizontalTimeline.tsx | 14 +- src/components/common/timelines/Timeline.tsx | 100 +- src/components/common/toaster/index.tsx | 21 +- src/components/common/toggles/Toggle.tsx | 2 +- src/components/common/tooltips/index.tsx | 116 +- src/components/diagrams/ButtonEdge.tsx | 2 +- src/components/diagrams/WorkflowNode.tsx | 10 +- src/components/files/IFrameViewer.tsx | 4 +- src/components/files/ImageViewer.tsx | 4 +- src/components/files/PreViewer.tsx | 4 +- src/components/files/TableViewer.tsx | 8 +- src/components/files/igv/IgvDesktop.tsx | 4 +- src/components/files/igv/IgvJs.tsx | 4 +- src/components/layouts/MainLayout.tsx | 15 +- src/components/layouts/files/FilesLayout.tsx | 2 +- src/components/layouts/lab/LibraryLayout.tsx | 4 +- src/components/layouts/lab/MetadataLayout.tsx | 2 +- .../lab/components/LibraryBreadCrumb.tsx | 4 +- .../lab/components/LibrarySideNavBar.tsx | 2 +- .../layouts/runs/RunsModuleLayout.tsx | 2 +- .../layouts/runs/RunsPageLayout.tsx | 2 +- .../navigation/breadcrumbs/index.tsx | 38 +- .../navigation/header/ThemeToggle.tsx | 17 + .../navigation/header/TokenDialog.tsx | 12 +- src/components/navigation/header/index.tsx | 128 +- .../navigation/navbar/ModuleNavBar.tsx | 34 +- .../navigation/navbar/SideNavBar.tsx | 16 +- .../navigation/tabs/ContentTabs.tsx | 10 +- src/components/navigation/tabs/LinkTabs.tsx | 2 +- src/components/tables/GroupedRowTable.tsx | 38 +- src/components/tables/Pagination.tsx | 56 +- src/components/tables/Table.tsx | 63 +- src/context/AmplifyAuthContext.tsx | 37 +- src/context/ThemeContext.tsx | 18 +- src/modules/auth/SignInPage.tsx | 14 +- src/modules/error/DevelopmentPage.tsx | 6 +- src/modules/error/NotFoundPage.tsx | 6 +- src/modules/files/components/FileAPITable.tsx | 15 +- .../files/components/FileDownloadButton.tsx | 4 +- .../files/components/FilePreviewDrawer.tsx | 10 +- .../files/components/InputBadgeBox.tsx | 14 +- src/modules/files/pages/files.tsx | 2 +- .../individual/IndividualTableFilter.tsx | 10 +- .../lab/components/individual/utils.tsx | 3 +- .../library/LibraryAnalysisReportTable.tsx | 12 +- .../library/LibraryTableDetails.tsx | 6 +- .../components/library/LibraryTableFilter.tsx | 24 +- .../library/PortalRunIdDropdown.tsx | 6 +- .../components/library/WorkflowVersion.tsx | 4 +- src/modules/lab/components/library/utils.tsx | 2 +- .../components/project/ProjectTableFilter.tsx | 10 +- src/modules/lab/components/project/utils.tsx | 2 +- .../components/sample/SampleTableFilter.tsx | 16 +- src/modules/lab/components/sample/utils.tsx | 2 +- .../subject/SubjectListAPITable.tsx | 7 +- .../components/subject/SubjectTableFilter.tsx | 16 +- src/modules/lab/components/subject/utils.tsx | 4 +- src/modules/lab/components/utils.tsx | 8 +- src/modules/lab/pages/Metadata.tsx | 8 +- src/modules/lab/pages/Sync.tsx | 34 +- .../lab/pages/library/LibraryOverview.tsx | 10 +- .../lab/pages/library/LibraryWorkflow.tsx | 6 +- src/modules/runs/Pages/AnalysisRuns.tsx | 2 +- .../runs/Pages/AnalysisRunsDetails.tsx | 2 +- src/modules/runs/Pages/SequenceRuns.tsx | 2 +- src/modules/runs/Pages/WorkflowRuns.tsx | 2 +- .../runs/Pages/WorkflowRunsDetails.tsx | 2 +- .../analysisRuns/AnalysisRunDetailsTable.tsx | 4 +- .../AnalysisRunDetailsWorkflowRuns.tsx | 4 +- .../analysisRuns/AnalysisRunFilterHeader.tsx | 6 +- .../analysisRuns/AnalysisRunTable.tsx | 8 +- .../sequenceRuns/SequenceRunFilterHeader.tsx | 6 +- .../sequenceRuns/SequenceRunTable.tsx | 2 +- .../sequenceRuns/SequenceRunTimeline.tsx | 154 +- .../workflowRuns/WorkflowRunDetailsTable.tsx | 26 +- .../workflowRuns/WorkflowRunFilterHeader.tsx | 6 +- .../workflowRuns/WorkflowRunTable.tsx | 2 +- .../workflowRuns/WorkflowRunTimeline.tsx | 600 ++- src/modules/runs/index.tsx | 12 +- src/router/index.tsx | 15 +- src/stories/Button.stories.tsx | 2 +- src/stories/Diagram.stories.tsx | 12 +- src/stories/Dialog.stories.tsx | 2 +- src/stories/Dropdowns.stories.tsx | 6 +- src/stories/Toast.stories.tsx | 2 +- src/styles/additional-styles/flatpickr.css | 10 +- .../additional-styles/utility-patterns.css | 12 +- src/utils/commonUtils.ts | 45 +- tailwind.config.js | 1 + yarn.lock | 3568 ++++++++--------- 116 files changed, 3249 insertions(+), 2953 deletions(-) rename src/components/{ => common}/dialogs/SimpleDialog.tsx (64%) rename src/components/{ => common}/dialogs/index.tsx (100%) create mode 100644 src/components/navigation/header/ThemeToggle.tsx diff --git a/eslint.config.js b/eslint.config.js index 4451622..dd2404c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -61,4 +61,17 @@ export default [ }, }, }, + { + rules: { + 'no-unused-expressions': 'off', + '@typescript-eslint/no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + allowTaggedTemplates: true, + }, + ], + }, + }, ]; diff --git a/package.json b/package.json index 767d96a..d82e317 100644 --- a/package.json +++ b/package.json @@ -22,14 +22,14 @@ }, "dependencies": { "@headlessui/react": "^2.2.0", - "@heroicons/react": "^2.1.5", - "@tanstack/react-query": "^5.59.19", - "@xyflow/react": "^12.3.4", - "aws-amplify": "^6.8.0", + "@heroicons/react": "^2.2.0", + "@tanstack/react-query": "^5.62.7", + "@xyflow/react": "^12.3.6", + "aws-amplify": "^6.10.3", "clsx": "^2.1.1", "d3": "^7.9.0", "dayjs": "^1.11.13", - "igv": "^3.0.9", + "igv": "^3.1.2", "mime-db": "^1.53.0", "openapi-fetch": "^0.13.0", "react": "^18.3.1", @@ -38,14 +38,14 @@ "react-flatpickr": "^3.10.13", "react-loading-skeleton": "^3.5.0", "react-router-dom": "^6.27.0", - "react-toastify": "^10.0.6", - "tailwind-merge": "^2.5.4", + "react-toastify": "^11.0.0", + "tailwind-merge": "^2.5.5", "unsplash-js": "^7.0.19" }, "devDependencies": { "@chromatic-com/storybook": "^3.2.2", "@eslint/compat": "^1.2.2", - "@eslint/js": "^9.14.0", + "@eslint/js": "^9.17.0", "@storybook/addon-essentials": "^8.4.1", "@storybook/addon-interactions": "^8.4.1", "@storybook/addon-links": "^8.4.1", @@ -60,11 +60,11 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/react-flatpickr": "^3.8.11", - "@typescript-eslint/eslint-plugin": "^8.12.2", - "@typescript-eslint/parser": "^8.12.2", + "@typescript-eslint/eslint-plugin": "^8.18.1", + "@typescript-eslint/parser": "^8.18.1", "@vitejs/plugin-react": "^4.3.3", "autoprefixer": "^10.4.20", - "eslint": "^9.14.0", + "eslint": "^9.17.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.2", @@ -72,16 +72,17 @@ "eslint-plugin-react-refresh": "^0.4.14", "eslint-plugin-storybook": "^0.10.2", "globals": "^15.11.0", - "openapi-typescript": "^7.4.2", + "openapi-typescript": "^7.4.4", "postcss": "^8.4.47", - "prettier": "^3.3.3", + "prettier": "^3.4.2", + "prettier-plugin-tailwindcss": "^0.6.9", "rollup-plugin-visualizer": "^5.12.0", "storybook": "^8.4.1", "storybook-addon-remix-react-router": "^3.0.1", "storybook-react-context": "^0.7.0", "tailwindcss": "^3.4.14", - "typescript": "^5.6.3", - "typescript-eslint": "^8.12.2", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.1", "vite": "^5.4.10", "vite-plugin-checker": "^0.8.0" }, diff --git a/prettier.config.js b/prettier.config.js index 0a2b72a..df1411c 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -14,4 +14,7 @@ export default { trailingComma: 'es5', useTabs: false, endOfLine: 'lf', + + // tailwindcss + plugins: ['prettier-plugin-tailwindcss'], }; diff --git a/src/App.tsx b/src/App.tsx index 704f0c3..78a4436 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,15 +2,18 @@ import Router from '@/router'; import { ToastContainer } from 'react-toastify'; import { AuthProvider } from '@/context/AmplifyAuthContext'; import { ReactQueryClientProvider } from '@/context/QueryClientContext'; +import { ThemeProvider } from '@/context/ThemeContext'; function App() { return ( - - - - - - + + + + + + + + ); } diff --git a/src/components/common/backdrop/BackdropWithText.tsx b/src/components/common/backdrop/BackdropWithText.tsx index 70303d0..17a6dac 100644 --- a/src/components/common/backdrop/BackdropWithText.tsx +++ b/src/components/common/backdrop/BackdropWithText.tsx @@ -18,7 +18,7 @@ const BackdropWithText: FC = ({ return (
diff --git a/src/components/common/badges/StatusBadge.tsx b/src/components/common/badges/StatusBadge.tsx index 8bbf9fd..14fcad4 100644 --- a/src/components/common/badges/StatusBadge.tsx +++ b/src/components/common/badges/StatusBadge.tsx @@ -1,14 +1,17 @@ +/* eslint-disable react-refresh/only-export-components */ +// https://github.com/ArnaudBarre/eslint-plugin-react-refresh/issues/25#issuecomment-1729071347 + import { Badge, getBadgeType } from '.'; import { StatusIcon } from '../statusIcon'; import { classNames } from '@/utils/commonUtils'; const StatusBadge = ({ status }: { status: string }) => { return ( - -
+ +
{status} diff --git a/src/components/common/buttons/Button.tsx b/src/components/common/buttons/Button.tsx index f7e2a52..295f682 100644 --- a/src/components/common/buttons/Button.tsx +++ b/src/components/common/buttons/Button.tsx @@ -1,5 +1,6 @@ import { FC, ReactNode, MouseEventHandler } from 'react'; import { classNames } from '@/utils/commonUtils'; +import { Tooltip } from '@/components/common/tooltips'; export interface ButtonProps { type?: 'primary' | 'secondary' | 'light' | 'green' | 'red' | 'yellow' | 'gray'; @@ -9,6 +10,10 @@ export interface ButtonProps { onClick?: MouseEventHandler; className?: string; disabled?: boolean; + loading?: boolean; + tooltip?: string; + tooltipPosition?: 'top' | 'bottom' | 'left' | 'right'; + tooltipBackground?: 'light' | 'dark'; } const Button: FC = ({ @@ -19,72 +24,94 @@ const Button: FC = ({ onClick, className = '', disabled = false, + loading = false, + tooltip, + tooltipPosition = 'top', + tooltipBackground = 'dark', }) => { const baseStyles = - 'font-normal text-center py-1.5 px-3 text-sm shadow-sm transition-colors duration-300 transform focus:outline-none focus:ring-opacity-80 flex items-center gap-x-2 '; + 'relative inline-flex gap-2 items-center justify-center font-medium tracking-wide transition-all duration-200 ease-in-out focus:outline-none focus:ring-1 focus:ring-offset-2 active:transform active:scale-90 disabled:opacity-70 disabled:cursor-not-allowed disabled:transform-none'; + const typeStyles: { [key: string]: string } = { primary: - ' text-white bg-blue-700' + - ' hover:bg-blue-800' + - ' focus:ring-1 focus:ring-blue-300' + - ' dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800', + 'text-white bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 dark:bg-blue-500 dark:hover:bg-blue-600' + + ' shadow-md hover:shadow-lg', secondary: - ' text-blue-700 bg-white' + - ' border border-blue-700' + - ' hover:bg-gray-100 hover:text-blue-700' + - ' focus:z-10 focus:ring-1 focus:ring-blue-300' + - ' dark:focus:ring-blue-700 dark:bg-gray-800 dark:text-blue-700 dark:border-gray-600 dark:hover:text-blue-700 dark:hover:bg-gray-700', + 'text-blue-700 bg-blue-100 hover:bg-blue-200 focus:ring-blue-500 dark:bg-blue-200 dark:hover:bg-blue-300' + + ' dark:text-blue-800', light: - ' text-gray-900 bg-white' + - ' border border-gray-300' + - ' hover:bg-gray-100' + - ' focus:ring-1 focus:ring-gray-100 ' + - ' dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700', + 'text-gray-700 bg-white hover:bg-gray-50 focus:ring-gray-500 dark:bg-gray-800 dark:text-gray-100' + + ' dark:hover:bg-gray-700 border border-gray-300 dark:border-gray-600', green: - ' text-white bg-green-700' + - ' hover:bg-green-800' + - ' focus:ring-1 focus:ring-green-300' + - ' dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800', + 'text-white bg-green-600 hover:bg-green-700 focus:ring-green-500 dark:bg-green-500 dark:hover:bg-green-600' + + ' shadow-md hover:shadow-lg', red: - ' text-white bg-red-700 ' + - ' hover:bg-red-800' + - ' focus:ring-1 focus:ring-red-300' + - ' dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900', + 'text-white bg-red-600 hover:bg-red-700 focus:ring-red-500 dark:bg-red-500 dark:hover:bg-red-600' + + ' shadow-md hover:shadow-lg', yellow: - ' text-white bg-yellow-400' + - ' hover:bg-yellow-500' + - ' focus:ring-1 focus:ring-yellow-300' + - ' dark:focus:ring-yellow-900', - gray: 'text-gray-500' + ' hover:bg-magpie-light-50' + ' focus:ring-1 focus:ring-blue-500/50', + 'text-white bg-yellow-500 hover:bg-yellow-600 focus:ring-yellow-500 dark:bg-yellow-400 dark:hover:bg-yellow-500' + + ' shadow-md hover:shadow-lg', + gray: + 'text-gray-700 bg-gray-100 hover:bg-gray-200 focus:ring-gray-500 dark:bg-gray-700 dark:text-gray-100' + + ' dark:hover:bg-gray-600', }; const sizeStyles: { [key: string]: string } = { - xs: ' text-xs px-2 py-1 ', - sm: ' text-sm px-3 py-1.5 ', - md: ' text-md px-4 py-2 ', - lg: ' text-lg px-5 py-2.5 ', + xs: 'text-xs px-2.5 py-1.5', + sm: 'text-sm px-3 py-2', + md: 'text-base px-4 py-2', + lg: 'text-lg px-6 py-3', }; - const roundedStyles = rounded ? ' rounded-full ' : ' rounded '; - const disabledStyles = disabled ? ' opacity-50 cursor-not-allowed hover:!bg-transparent' : ' '; - - return ( + const button = ( ); + + if (tooltip) { + return ( + + {button} + + ); + } + + return button; }; export default Button; diff --git a/src/components/common/buttons/IconButton.tsx b/src/components/common/buttons/IconButton.tsx index cfb3e9a..e7b4429 100644 --- a/src/components/common/buttons/IconButton.tsx +++ b/src/components/common/buttons/IconButton.tsx @@ -3,13 +3,13 @@ import { Tooltip } from '@/components/common/tooltips'; export interface IconButtonProps { icon: ReactNode; - tooltip?: string; onClick?: MouseEventHandler; type?: 'primary' | 'secondary' | 'light' | 'green' | 'red' | 'yellow' | 'gray'; disabled?: boolean; className?: string; + tooltip?: string; tooltipPosition?: 'top' | 'bottom' | 'left' | 'right'; - tooltipBackground?: 'gray' | 'white'; + tooltipBackground?: 'light' | 'dark'; } const IconButton: FC = ({ @@ -19,7 +19,7 @@ const IconButton: FC = ({ disabled = false, className = '', tooltipPosition = 'top', - tooltipBackground = 'white', + tooltipBackground = 'dark', }) => { const baseIconButtonStyles = 'p-1.5 rounded-md text-gray-400 hover:text-gray-600 hover:bg-gray-100'; diff --git a/src/components/common/checkbox/Checkbox.tsx b/src/components/common/checkbox/Checkbox.tsx index 24d2395..81c1006 100644 --- a/src/components/common/checkbox/Checkbox.tsx +++ b/src/components/common/checkbox/Checkbox.tsx @@ -23,7 +23,7 @@ const Checkbox: FC = ({ className, checked, onChange, disabled, l checked={isChecked} onChange={onChange} disabled={disabled || false} - className='group p-[1px] size-4 rounded border bg-gray-100 border-gray-300 cursor-pointer data-[checked]:bg-blue-600 data-[disabled]:bg-gray-100 data-[disabled]:text-gray-400 data-[disabled]:cursor-not-allowed' + className='group size-4 cursor-pointer rounded border border-gray-300 bg-gray-100 p-[1px] data-[disabled]:cursor-not-allowed data-[checked]:bg-blue-600 data-[disabled]:bg-gray-100 data-[disabled]:text-gray-400' > = ({ className, checked, onChange, disabled, l
- = ({ align, startDate, endDate, onOpen={() => setIsOpen(true)} onClose={() => setIsOpen(false)} /> -
+
diff --git a/src/components/dialogs/SimpleDialog.tsx b/src/components/common/dialogs/SimpleDialog.tsx similarity index 64% rename from src/components/dialogs/SimpleDialog.tsx rename to src/components/common/dialogs/SimpleDialog.tsx index 3277358..7918883 100644 --- a/src/components/dialogs/SimpleDialog.tsx +++ b/src/components/common/dialogs/SimpleDialog.tsx @@ -35,40 +35,48 @@ const SimpleDialog: FC = ({ -
-
+
+
-
+
{TitleIcon && ( -
-
diff --git a/src/components/common/drawers/SideDrawer.tsx b/src/components/common/drawers/SideDrawer.tsx index b0f155e..35a9f34 100644 --- a/src/components/common/drawers/SideDrawer.tsx +++ b/src/components/common/drawers/SideDrawer.tsx @@ -28,47 +28,54 @@ const SideDrawer: FC = ({ }) => { return ( - */} +
-
+
{/* Header */} -
+
- + {title} - {subtitle &&

{subtitle}

} + {subtitle && ( +

{subtitle}

+ )}
- {/* Divider container */} -
-
{children}
+ {/* Content */} +
+
{children}
diff --git a/src/components/common/dropdowns/Dropdown.tsx b/src/components/common/dropdowns/Dropdown.tsx index 0052d08..d8fb960 100644 --- a/src/components/common/dropdowns/Dropdown.tsx +++ b/src/components/common/dropdowns/Dropdown.tsx @@ -27,11 +27,11 @@ const Dropdown: FC = ({ }) => { return (
- + {floatingLabel && (
); } diff --git a/src/components/common/json-to-table/json-display.tsx b/src/components/common/json-to-table/json-display.tsx index 5b5afb1..0b98c6a 100644 --- a/src/components/common/json-to-table/json-display.tsx +++ b/src/components/common/json-to-table/json-display.tsx @@ -12,27 +12,44 @@ interface JsonDisplayProps { const JsonDisplay: FC = ({ isFetchingData, data }) => { return ( -
+
{isFetchingData ? : null} {data ? ( -
-
+        
+
             {JSON.stringify(data || {}, null, 2)}
           
- { - navigator.clipboard.writeText(JSON.stringify(data || {}, null, 2)); - toaster.success({ - title: `Copied data to clipboard`, - }); - }} - /> +
+ { + navigator.clipboard.writeText(JSON.stringify(data || {}, null, 2)); + toaster.success({ + title: 'Copied to clipboard', + }); + }} + /> +
) : ( -
+
{[...Array(10)].map((_, index) => ( - + ))}
)} diff --git a/src/components/common/json-to-table/json-to-list.tsx b/src/components/common/json-to-table/json-to-list.tsx index 238df8a..0f1e5dd 100644 --- a/src/components/common/json-to-table/json-to-list.tsx +++ b/src/components/common/json-to-table/json-to-list.tsx @@ -24,41 +24,61 @@ const JsonToList: FC = ({ if (isFetchingData) { return ( -
+
- +
- +
); } return ( -
-
- {title &&

{title}

} - {subtitle &&

{subtitle}

} +
+
+ {title && ( +

+ {title} +

+ )} + {subtitle && ( +

+ {subtitle} +

+ )}
-
-
+
+
{listData ? ( Object.entries(listData).map(([key, value], index) => ( -
-
{key}
-
+
+
+ {key} +
+
{value}
)) ) : ( -
-
No data found
+
+
+ No data found +
)}
diff --git a/src/components/common/json-to-table/json-to-nested-list.tsx b/src/components/common/json-to-table/json-to-nested-list.tsx index c08cc32..d4f8eb4 100644 --- a/src/components/common/json-to-table/json-to-nested-list.tsx +++ b/src/components/common/json-to-table/json-to-nested-list.tsx @@ -32,21 +32,26 @@ const JsonToNestedList: FC = ({ const renderValue = (value: any) => { if (Array.isArray(value)) { return ( -
    +
      {value.map((item, index) => ( -
    • {renderValue(item)}
    • +
    • + {renderValue(item)} +
    • ))}
    ); } else if (typeof value === 'object' && value !== null) { return ( -
    +
    {Object.entries(value).map(([key, val], index) => ( -
    -
    +
    +
    {key}
    -
    +
    {renderValue(val)}
    @@ -56,44 +61,57 @@ const JsonToNestedList: FC = ({ } else if (cellValueFormat && cellValueFormat.condition(value)) { return cellValueFormat.cell(value); } else { - return {value}; + return {value}; } }; if (!listData && isFetchingData) { return ( -
    +
    - +
    - +
    ); } return ( -
    -
    - {title &&

    {title}

    } - {subtitle &&

    {subtitle}

    } +
    +
    + {title && ( +

    {title}

    + )} + {subtitle && ( +

    + {subtitle} +

    + )}
    {listData && isFetchingData ? ( ) : null} -
    +
    {listData ? ( renderValue(listData) ) : ( -
    -
    No data found
    +
    +

    No data found

    )}
    diff --git a/src/components/common/json-to-table/json-to-table.tsx b/src/components/common/json-to-table/json-to-table.tsx index 84b3692..232c336 100644 --- a/src/components/common/json-to-table/json-to-table.tsx +++ b/src/components/common/json-to-table/json-to-table.tsx @@ -1,13 +1,15 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import React from 'react'; -const keyClassName = 'font-bold px-4 text-sm'; -const valueClassName = 'py-2 text-sm'; -const rowClassName = 'even:bg-gray-50'; const JsonToTable = ({ data }: { data: Record }) => { + const keyClassName = 'font-medium px-4 py-3 text-sm text-gray-700 dark:text-gray-300'; + const valueClassName = 'px-4 py-3 text-sm text-gray-600 dark:text-gray-400'; + const rowClassName = + 'border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors'; + const renderValue = (value: any) => { if (!value) { - return '-'; + return -; } if (React.isValidElement(value)) { @@ -15,25 +17,27 @@ const JsonToTable = ({ data }: { data: Record }) => { } if (Array.isArray(value)) { - return value.length > 0 - ? value.map((item, idx) => ( -
    - {item} -
    - )) - : '-'; + return value.length > 0 ? ( + value.map((item, idx) => ( +
    + {item} +
    + )) + ) : ( + - + ); } if (typeof value === 'object') { return ; } - return value.toString(); + return {value.toString()}; }; return ( - - +
    + {Object.entries(data).map(([key, value]) => ( diff --git a/src/components/common/search/Search.tsx b/src/components/common/search/Search.tsx index 64b1688..2b2060e 100644 --- a/src/components/common/search/Search.tsx +++ b/src/components/common/search/Search.tsx @@ -7,9 +7,16 @@ interface SearchProps { hasTooltip?: boolean; tooltipText?: string; onSearch: (search: string | null) => void; + placeholder?: string; } -const Search: FC = ({ onSearch, searchBoxContent, hasTooltip, tooltipText }) => { +const Search: FC = ({ + onSearch, + searchBoxContent, + hasTooltip, + tooltipText, + placeholder, +}) => { const [searchBox, setSearchBox] = useState(''); const [isFocused, setIsFocused] = useState(false); const [isHovered, setIsHovered] = useState(false); @@ -23,18 +30,21 @@ const Search: FC = ({ onSearch, searchBoxContent, hasTooltip, toolt }, [searchBoxContent, hasTooltip]); return ( -
    -
    +
    +
    setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} >
    -
    { @@ -50,19 +60,19 @@ const Search: FC = ({ onSearch, searchBoxContent, hasTooltip, toolt value={searchBox} id='search' name='search' - className='block w-full h-8 rounded-md border-0 bg-white py-1.5 pl-10 pr-3 text-gray-900 ring-1 ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6' - placeholder='Search' + className='block h-8 w-full rounded-md border-0 bg-white py-1.5 pl-10 pr-3 text-sm text-gray-900 ring-1 ring-gray-300 transition-all duration-200 ease-in-out placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-600 dark:bg-gray-800 dark:text-gray-100 dark:ring-gray-700 dark:placeholder:text-gray-500 dark:focus:ring-blue-500' + placeholder={placeholder} type='search' /> {showXMark && (
    { setSearchBox(''); onSearch(null); }} > -
    )}
    @@ -71,12 +81,11 @@ const Search: FC = ({ onSearch, searchBoxContent, hasTooltip, toolt - + )}
    diff --git a/src/components/common/select/IconMultipleSelect.tsx b/src/components/common/select/IconMultipleSelect.tsx index a11b0ad..ef89966 100644 --- a/src/components/common/select/IconMultipleSelect.tsx +++ b/src/components/common/select/IconMultipleSelect.tsx @@ -63,13 +63,13 @@ const IconMultipleSelect: FC = ({ = ({ {hasSelected ? ( ) : ( - + )} -
    +
    Filters
    {options.map((option, key) => (
    {option.label && ( - + item === option.value)} @@ -133,7 +133,7 @@ const IconMultipleSelect: FC = ({ } }} disabled={option.disabled || false} - className='group p-[1px] size-4 rounded border bg-gray-100 border-gray-300 cursor-pointer data-[checked]:bg-blue-600 data-[disabled]:bg-gray-100 data-[disabled]:text-gray-400 data-[disabled]:cursor-not-allowed' + className='group size-4 cursor-pointer rounded border border-gray-300 bg-gray-100 p-[1px] data-[disabled]:cursor-not-allowed data-[checked]:bg-blue-600 data-[disabled]:bg-gray-100 data-[disabled]:text-gray-400' > = ({ -
    {key}