From e59e0f57d397f0625d116e762c77863916de4561 Mon Sep 17 00:00:00 2001
From: viktorstrate <viktorstrate@gmail.com>
Date: Tue, 13 Jul 2021 14:32:35 +0200
Subject: [PATCH] Style face action modal content

---
 .../SingleFaceGroup/SelectFaceGroupTable.tsx  | 114 ++++++++--------
 .../SingleFaceGroup/SelectImageFacesTable.tsx | 124 ++++++++----------
 ui/src/components/sidebar/Sidebar.tsx         |   7 +-
 ui/src/primitives/Modal.tsx                   |   4 +-
 ui/src/primitives/Table.tsx                   |  10 +-
 5 files changed, 121 insertions(+), 138 deletions(-)

diff --git a/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectFaceGroupTable.tsx b/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectFaceGroupTable.tsx
index d7ef5fb..d81077f 100644
--- a/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectFaceGroupTable.tsx
+++ b/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectFaceGroupTable.tsx
@@ -1,7 +1,15 @@
-import React, { useState, useEffect } from 'react'
+import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import { Input, Pagination, Table } from 'semantic-ui-react'
 import styled from 'styled-components'
+import { TextField } from '../../../primitives/form/Input'
+import {
+  Table,
+  TableBody,
+  TableCell,
+  TableHeader,
+  TableHeaderCell,
+  TableRow,
+} from '../../../primitives/Table'
 import FaceCircleImage from '../FaceCircleImage'
 import { myFaces_myFaceGroups } from '../__generated__/myFaces'
 import { singleFaceGroup_faceGroup } from './__generated__/singleFaceGroup'
@@ -13,7 +21,7 @@ const FaceCircleWrapper = styled.div<{ $selected: boolean }>`
     ${({ $selected }) => ($selected ? `#2185c9` : 'rgba(255,255,255,0)')};
 `
 
-const FlexCell = styled(Table.Cell)`
+const FlexCell = styled(TableCell)`
   display: flex;
   align-items: center;
 `
@@ -21,6 +29,7 @@ const FlexCell = styled(Table.Cell)`
 export const RowLabel = styled.span<{ $selected: boolean }>`
   ${({ $selected }) => $selected && `font-weight: bold;`}
   margin-left: 12px;
+  width: 100%;
 `
 
 type FaceGroupRowProps = {
@@ -35,7 +44,7 @@ const FaceGroupRow = ({
   setFaceSelected,
 }: FaceGroupRowProps) => {
   return (
-    <Table.Row key={faceGroup.id} onClick={setFaceSelected}>
+    <TableRow key={faceGroup.id} onClick={setFaceSelected}>
       <FlexCell>
         <FaceCircleWrapper $selected={faceSelected}>
           <FaceCircleImage
@@ -44,9 +53,15 @@ const FaceGroupRow = ({
             selectable={false}
           />
         </FaceCircleWrapper>
-        <RowLabel $selected={faceSelected}>{faceGroup.label}</RowLabel>
+        <span
+          className={`ml-3 ${faceSelected ? 'font-semibold' : ''} ${
+            !faceGroup.label ? 'text-gray-500 italic' : ''
+          }`}
+        >
+          {faceGroup.label ?? 'Unlabeled'}
+        </span>
       </FlexCell>
-    </Table.Row>
+    </TableRow>
   )
 }
 
@@ -69,14 +84,14 @@ const SelectFaceGroupTable = ({
 }: SelectFaceGroupTableProps) => {
   const { t } = useTranslation()
 
-  const PAGE_SIZE = 6
+  // const PAGE_SIZE = 6
 
-  const [page, setPage] = useState(0)
+  // const [page, setPage] = useState(0)
   const [searchValue, setSearchValue] = useState('')
 
-  useEffect(() => {
-    setPage(0)
-  }, [searchValue])
+  // useEffect(() => {
+  //   setPage(0)
+  // }, [searchValue])
 
   const rows = faceGroups
     .filter(
@@ -93,55 +108,38 @@ const SelectFaceGroupTable = ({
       />
     ))
 
-  const pageRows = rows.filter(
-    (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
-  )
+  // const pageRows = rows.filter(
+  //   (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
+  // )
 
   return (
-    <Table selectable>
-      <Table.Header>
-        <Table.Row>
-          <Table.HeaderCell>{title}</Table.HeaderCell>
-        </Table.Row>
-        <Table.Row>
-          <Table.HeaderCell>
-            <Input
-              value={searchValue}
-              onChange={e => setSearchValue(e.target.value)}
-              icon="search"
-              placeholder={t(
-                'people_page.table.select_face_group.search_faces_placeholder',
-                'Search faces...'
-              )}
-              fluid
-            />
-          </Table.HeaderCell>
-        </Table.Row>
-      </Table.Header>
-      <Table.Body>{pageRows}</Table.Body>
-      <Table.Footer>
-        <Table.Row>
-          <Table.HeaderCell>
-            <Pagination
-              floated="right"
-              firstItem={null}
-              lastItem={null}
-              // nextItem={null}
-              // prevItem={null}
-              activePage={page + 1}
-              totalPages={Math.ceil(rows.length / PAGE_SIZE)}
-              onPageChange={(_, { activePage }) => {
-                if (activePage) {
-                  setPage(Math.ceil(activePage as number) - 1)
-                } else {
-                  setPage(0)
-                }
-              }}
-            />
-          </Table.HeaderCell>
-        </Table.Row>
-      </Table.Footer>
-    </Table>
+    <>
+      <Table className="w-full">
+        <TableHeader>
+          <TableRow>
+            <TableHeaderCell>{title}</TableHeaderCell>
+          </TableRow>
+          <TableRow>
+            <TableHeaderCell>
+              <TextField
+                fullWidth
+                value={searchValue}
+                onChange={e => setSearchValue(e.target.value)}
+                placeholder={t(
+                  'people_page.tableselect_face_group.search_faces_placeholder',
+                  'Search faces...'
+                )}
+              />
+            </TableHeaderCell>
+          </TableRow>
+        </TableHeader>
+      </Table>
+      <div className="overflow-auto max-h-[500px] mt-2">
+        <Table className="w-full">
+          <TableBody>{rows}</TableBody>
+        </Table>
+      </div>
+    </>
   )
 }
 
diff --git a/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectImageFacesTable.tsx b/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectImageFacesTable.tsx
index b33b057..360cd7d 100644
--- a/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectImageFacesTable.tsx
+++ b/ui/src/Pages/PeoplePage/SingleFaceGroup/SelectImageFacesTable.tsx
@@ -1,10 +1,18 @@
-import React, { useEffect, useState } from 'react'
+import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import { Checkbox, Input, Pagination, Table } from 'semantic-ui-react'
 import styled from 'styled-components'
 import { ProtectedImage } from '../../../components/photoGallery/ProtectedMedia'
+import Checkbox from '../../../primitives/form/Checkbox'
+import { TextField } from '../../../primitives/form/Input'
+import {
+  Table,
+  TableBody,
+  TableCell,
+  TableHeader,
+  TableHeaderCell,
+  TableRow,
+} from '../../../primitives/Table'
 import { myFaces_myFaceGroups_imageFaces } from '../__generated__/myFaces'
-import { RowLabel } from './SelectFaceGroupTable'
 import { singleFaceGroup_faceGroup_imageFaces } from './__generated__/singleFaceGroup'
 
 const SelectImagePreview = styled(ProtectedImage)`
@@ -26,22 +34,21 @@ const ImageFaceRow = ({
   setFaceSelected,
 }: ImageFaceRowProps) => {
   return (
-    <Table.Row key={imageFace.id}>
-      <Table.Cell>
-        <Checkbox checked={faceSelected} onChange={setFaceSelected} />
-      </Table.Cell>
-      <Table.Cell>
+    <TableRow key={imageFace.id}>
+      <TableCell>
         <SelectImagePreview
           src={imageFace.media.thumbnail?.url}
           onClick={setFaceSelected}
         />
-      </Table.Cell>
-      <Table.Cell width={16}>
-        <RowLabel $selected={faceSelected} onClick={setFaceSelected}>
-          {imageFace.media.title}
-        </RowLabel>
-      </Table.Cell>
-    </Table.Row>
+      </TableCell>
+      <TableCell className="min-w-64 w-full">
+        <Checkbox
+          label={imageFace.media.title}
+          checked={faceSelected}
+          onChange={setFaceSelected}
+        />
+      </TableCell>
+    </TableRow>
   )
 }
 
@@ -70,14 +77,14 @@ const SelectImageFacesTable = ({
 }: SelectImageFacesTable) => {
   const { t } = useTranslation()
 
-  const PAGE_SIZE = 6
+  // const PAGE_SIZE = 6
 
-  const [page, setPage] = useState(0)
+  // const [page, setPage] = useState(0)
   const [searchValue, setSearchValue] = useState('')
 
-  useEffect(() => {
-    setPage(0)
-  }, [searchValue])
+  // useEffect(() => {
+  //   setPage(0)
+  // }, [searchValue])
 
   const rows = imageFaces
     .filter(
@@ -102,55 +109,38 @@ const SelectImageFacesTable = ({
       />
     ))
 
-  const pageRows = rows.filter(
-    (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
-  )
+  // const pageRows = rows.filter(
+  //   (_, i) => i >= page * PAGE_SIZE && i < (page + 1) * PAGE_SIZE
+  // )
 
   return (
-    <Table selectable>
-      <Table.Header>
-        <Table.Row>
-          <Table.HeaderCell colSpan={3}>{title}</Table.HeaderCell>
-        </Table.Row>
-        <Table.Row>
-          <Table.HeaderCell colSpan={3}>
-            <Input
-              value={searchValue}
-              onChange={e => setSearchValue(e.target.value)}
-              icon="search"
-              placeholder={t(
-                'people_page.table.select_image_faces.search_images_placeholder',
-                'Search images...'
-              )}
-              fluid
-            />
-          </Table.HeaderCell>
-        </Table.Row>
-      </Table.Header>
-      <Table.Body>{pageRows}</Table.Body>
-      <Table.Footer>
-        <Table.Row>
-          <Table.HeaderCell colSpan={3}>
-            <Pagination
-              floated="right"
-              firstItem={null}
-              lastItem={null}
-              // nextItem={null}
-              // prevItem={null}
-              activePage={page + 1}
-              totalPages={Math.ceil(rows.length / PAGE_SIZE)}
-              onPageChange={(_, { activePage }) => {
-                if (activePage) {
-                  setPage(Math.ceil(activePage as number) - 1)
-                } else {
-                  setPage(0)
-                }
-              }}
-            />
-          </Table.HeaderCell>
-        </Table.Row>
-      </Table.Footer>
-    </Table>
+    <>
+      <Table className="w-full">
+        <TableHeader>
+          <TableRow>
+            <TableHeaderCell colSpan={2}>{title}</TableHeaderCell>
+          </TableRow>
+          <TableRow>
+            <TableHeaderCell colSpan={2}>
+              <TextField
+                value={searchValue}
+                onChange={e => setSearchValue(e.target.value)}
+                placeholder={t(
+                  'people_page.tableselect_image_faces.search_images_placeholder',
+                  'Search images...'
+                )}
+                fullWidth
+              />
+            </TableHeaderCell>
+          </TableRow>
+        </TableHeader>
+      </Table>
+      <div className="overflow-auto max-h-[500px] mt-2">
+        <Table>
+          <TableBody>{rows}</TableBody>
+        </Table>
+      </div>
+    </>
   )
 }
 
diff --git a/ui/src/components/sidebar/Sidebar.tsx b/ui/src/components/sidebar/Sidebar.tsx
index aaafd63..2688ff9 100644
--- a/ui/src/components/sidebar/Sidebar.tsx
+++ b/ui/src/components/sidebar/Sidebar.tsx
@@ -1,5 +1,4 @@
 import React, { createContext, useContext, useEffect, useState } from 'react'
-import { FocusScope } from '@react-aria/focus'
 
 export type UpdateSidebarFn = (content: React.ReactNode) => void
 export type SidebarPinnedFn = (pin: boolean) => void
@@ -96,11 +95,7 @@ export const Sidebar = () => {
         pinned ? 'lg:border-l' : 'lg:shadow-separator'
       } lg:w-[420px] lg:right-0 lg:top-0 lg:z-40`}
     >
-      {content && (
-        <FocusScope contain={!pinned} restoreFocus={!pinned} autoFocus>
-          {content}
-        </FocusScope>
-      )}
+      {content}
       <div className="h-24"></div>
     </div>
   )
diff --git a/ui/src/primitives/Modal.tsx b/ui/src/primitives/Modal.tsx
index 9dc7c13..e266e22 100644
--- a/ui/src/primitives/Modal.tsx
+++ b/ui/src/primitives/Modal.tsx
@@ -46,8 +46,8 @@ const Modal = ({
       <div className="flex items-center justify-center min-h-screen">
         <Dialog.Overlay className="fixed inset-0 bg-black opacity-30" />
 
-        <div className="fixed bg-white rounded max-w-[calc(100%-16px)] mx-auto rounded shadow-md border">
-          <div className="p-2">
+        <div className="fixed bg-white max-w-[calc(100%-16px)] mx-auto rounded shadow-md border">
+          <div className="p-4">
             <Dialog.Title className="text-xl mb-1">{title}</Dialog.Title>
             <Dialog.Description className="text-sm mb-4">
               {description}
diff --git a/ui/src/primitives/Table.tsx b/ui/src/primitives/Table.tsx
index 4a5a80d..fffdfba 100644
--- a/ui/src/primitives/Table.tsx
+++ b/ui/src/primitives/Table.tsx
@@ -26,14 +26,14 @@ export const TableHeader = styled.thead.attrs({
   className: 'text-left',
 })``
 
-export const TableBody = styled.tbody.attrs({ className: '' })``
+export const TableBody = styled.tbody.attrs({ className: '' as string })``
 
-export const TableFooter = styled.tfoot.attrs({ className: '' })``
+export const TableFooter = styled.tfoot.attrs({ className: '' as string })``
 
-export const TableRow = styled.tr.attrs({ className: '' })``
+export const TableRow = styled.tr.attrs({ className: '' as string })``
 
 export const TableCell = styled.td.attrs({
-  className: 'py-2 px-2 align-top',
+  className: 'py-2 px-2 align-top' as string,
 })``
 
 export const TableHeaderCell = styled.th.attrs({
@@ -41,5 +41,5 @@ export const TableHeaderCell = styled.th.attrs({
 })``
 
 export const TableScrollWrapper = styled.div.attrs({
-  className: 'block overflow-x-auto whitespace-nowrap',
+  className: 'block overflow-x-auto whitespace-nowrap' as string,
 })``
