Skip to content

[_]: feat/list component#18

Merged
xabg2 merged 5 commits intomasterfrom
feature/mail-view
Mar 18, 2026
Merged

[_]: feat/list component#18
xabg2 merged 5 commits intomasterfrom
feature/mail-view

Conversation

@xabg2
Copy link
Contributor

@xabg2 xabg2 commented Mar 17, 2026

Adding new Tray List component so we can render the list of emails the user has.

Summary by CodeRabbit

Notas de la versión

  • Nuevas características

    • Carpeta Spam añadida al correo.
    • Nueva barra de búsqueda en correo con atajo de teclado.
    • Nuevo encabezado con filtros y acciones masivas.
    • Estado vacío visual mejorado para bandejas.
  • Actualizaciones

    • Etiquetas de navegación de correo renombradas para mayor claridad.
    • Vista de correo reestructurada a un diseño con cabecera y bandeja.

@xabg2 xabg2 requested a review from larryrider March 17, 2026 15:55
@xabg2 xabg2 self-assigned this Mar 17, 2026
@xabg2 xabg2 added the enhancement New feature or request label Mar 17, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Warning

Ignoring CodeRabbit configuration file changes. For security, only the configuration from the base branch is applied for open source repositories.

Walkthrough

Se elimina la mayor parte del diálogo de composición de mensajes (RichTextEditor, EditorBar, RecipientInput, ComposeMessageDialog, tipos y componentes adjuntos), se refactoriza el Sidenav y rutas (se agrega Spam), se reemplaza la utilidad de formateo de bytes por una nueva implementación con prettysize y se añaden componentes de UI de correo (Header, SearchInput, TrayEmptyState) y tipos asociados.

Changes

Cohort / File(s) Summary
Package & deps
package.json
Pin de @internxt/ui a =0.1.10, reemplazo de pretty-bytes por prettysize, y adición de react-device-detect y react-hotkeys-hook.
Compose message — eliminado
src/components/mail/composeMessageDialog/*
Eliminación completa de ComposeMessageDialog y todos sus subcomponentes, extensiones y tipos (RichTextEditor, EditorBar, fontSizeExtension, DefaultAttachmentItem, types: Attachment/Recipient/EditorBarItem).
Chips y pequeños UI eliminados
src/components/chips/RecipientChip.tsx
Se elimina el componente RecipientChip y su interfaz pública.
Sidenav y layout
src/components/Sidenav/index.tsx, src/routes/layouts/SidebarAndHeaderLayout.tsx
Renombrado/ajuste del componente Sidenav (SidenavWrapper → Sidenav), cambio de clave i18n a mail.title, y actualización de llamadas a bytesToString con nuevo objeto de opciones.
Bytes formatting — rework
src/utils/bytesToString/*, src/types/prettysize.d.ts
Eliminación de la implementación antigua; nueva función en src/utils/bytesToString/index.ts que usa prettysize, pruebas actualizadas; se añade declaración de tipos para prettysize.
Tests removidos/añadidos
src/utils/bytesToString.test.ts (removed), src/utils/bytesToString/bytesToString.test.ts (added)
Se elimina la antigua suite y se añade una nueva para la nueva API de bytesToString.
Nuevos componentes de correo
src/features/mail/components/header/index.tsx, src/features/mail/components/searchInput/index.tsx, src/features/mail/components/trayEmptyState/index.tsx
Se añaden Header (controles de filtrado y acciones masivas), SearchInput (con atajo Meta/Ctrl+F via react-hotkeys-hook) y TrayEmptyState (mensaje vacío).
MailView & tipos
src/features/mail/MailView.tsx, src/types/mail/index.ts
MailView ahora usa FolderType en lugar de string; se añade FolderType que incluye spam. UI reorganizada para usar Header y TrayEmptyState.
Navegación / rutas
src/hooks/navigation/useSidenavNavigation.tsx, src/routes/paths/index.ts
Se agrega la vista/ruta Spam (AppView.Spam, /spam) y se actualizan etiquetas de navegación de sidebar.* a mail.*.
i18n
src/i18n/locales/en.json
Renombramiento de sidebarmail, adición de filter, nuevas keys en actions, mail.spam y mail.tray.isEmpty.
Estilos
src/index.css
Selector .body reemplazado por :root, #root`` para overscroll-behavior.
Herramienta de revisión
.coderabbit.yaml
Actualización de configuración de idioma a en y añadidos ajustes de reviews/path_instructions.
Otros
src/utils/bytesToString.ts (removed)
Eliminada la antigua exportación envolviendo pretty-bytes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • larryrider
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive El título '[_]: feat/list component' es genérico y vago. No describe claramente el cambio principal del PR, que implica una refactorización significativa del componente de diálogo de composición de mensajes, cambios de dependencias y la introducción de nuevos componentes de lista. Se recomienda usar un título más descriptivo que resuma el cambio principal, como 'Refactor compose dialog and add mail tray list component' o 'Remove compose dialog and add mail list view'
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/mail-view
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@xabg2 xabg2 marked this pull request as ready for review March 17, 2026 16:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/features/mail/components/header/index.tsx`:
- Around line 60-68: The Checkbox component in the header lacks an accessible
label; update the Checkbox usage (the Checkbox element inside the flex row) to
provide an accessible name by either adding a descriptive aria-label prop (e.g.,
aria-label="Select all messages") or associating it with a visible or
visually-hidden <label> element tied to the Checkbox; ensure the label text
clearly describes the control (e.g., "Select all" or "Toggle selection") so
screen readers can identify it.
- Around line 40-51: The bulkActionContext menu currently uses XIcon for both
entries; update the archive entry (the object whose name is
translate('actions.archiveAll')) to use an appropriate archive icon (e.g.,
ArchiveIcon) instead of XIcon and add the corresponding import from
'@phosphor-icons/react' at the top of the file so the second item's icon
property references ArchiveIcon rather than XIcon.

In `@src/features/mail/components/searchInput/index.tsx`:
- Around line 28-31: Agregar un estado query en el componente SearchInput y
usarlo para controlar el input: crea const [query, setQuery] =
useState<string>('') dentro de SearchInput; pasar value={query} y onChange={(e)
=> setQuery(e.target.value)} al elemento input (manteniendo searchInput ref) y
reemplazar la cadena vacía hardcodeada en la llamada a
getClearButtonClassName('') por getClearButtonClassName(query); al limpiar
(botón clear) llamar setQuery('') y volver a enfocar con
searchInput.current?.focus() para que el botón de borrar aparezca y funcione
correctamente.
- Around line 62-68: The onKeyUpCapture handler is too late to stop default
arrow-key cursor movements; change the input's onKeyUpCapture to
onKeyDownCapture (or onKeyDown) on the same element in
src/features/mail/components/searchInput/index.tsx, moving the existing logic so
that Escape still calls e.currentTarget.blur() and ArrowUp/ArrowDown call
e.preventDefault() on keydown; keep the same key checks ('Escape', 'ArrowUp',
'ArrowDown') and ensure the event parameter type matches a KeyboardEvent for the
input element when you update the prop name.
- Around line 43-45: La firma de handleSubmit usa el tipo inexistente
React.SubmitEvent; cámbialo a un tipo válido como
SubmitEventHandler<HTMLFormElement> o React.SyntheticEvent<HTMLFormElement> (por
ejemplo: const handleSubmit = (e: SubmitEventHandler<HTMLFormElement> |
React.SyntheticEvent<HTMLFormElement>) => ...) para corregir la tipificación,
importando el tipo desde React si es necesario y manteniendo e.preventDefault()
dentro de la función; asegúrate de actualizar la declaración de handleSubmit en
el componente searchInput para reflejar el nuevo tipo.

In `@src/features/mail/components/trayEmptyState/index.tsx`:
- Line 14: The JSX currently concatenates folderName with
translate('mail.tray.isEmpty'), which breaks localization ordering; update the
component in trayEmptyState (where translate is called) to pass the folder name
as a variable via the translate props (e.g., translate('mail.tray.isEmpty', {
folder: folderName })), and update the translation key in locales
(mail.tray.isEmpty) to use interpolation like "{{folder}} is empty" so languages
can reorder the placeholder correctly.

In `@src/features/mail/MailView.tsx`:
- Around line 5-8: La unión de tipos FolderType no incluye 'spam', lo que choca
con el uso en MailView (prop folder en MailViewProps); actualiza la definición
de FolderType (símbolo FolderType en src/types/mail/index.ts) para añadir 'spam'
a la unión de literales (por ejemplo: 'inbox' | 'sent' | 'drafts' | 'trash' |
'spam') y reexporta/compila para que el componente MailView y la ruta que pasa
folder: 'spam' queden tipados correctamente.

In `@src/routes/layouts/SidebarAndHeaderLayout.tsx`:
- Line 3: Renombra el alias de importación `SidenavWrapper` a `Sidenav` y
actualiza todas las referencias en este módulo (por ejemplo cualquier uso de
`SidenavWrapper` en `SidebarAndHeaderLayout` o líneas alrededor de la import)
para usar `Sidenav` en su lugar; busca también la otra ocurrencia mencionada
(`SidenavWrapper` en la misma file around line 11) y cámbiala para mantener
consistencia de nombre y mejorar legibilidad.

In `@src/types/mail/index.ts`:
- Line 1: The FolderType union is missing the 'spam' variant which the app uses
in navigation/routes; update the exported type FolderType to include 'spam'
(i.e., add 'spam' to the union) so all code using FolderType (e.g., route
guards, navigation components) remains type-safe and aligned with runtime
values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ba2341c3-8ca3-4606-b5fd-364e06d8ec21

📥 Commits

Reviewing files that changed from the base of the PR and between 157b5fa and 6bfaafa.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (28)
  • package.json
  • src/components/Sidenav/index.tsx
  • src/components/chips/RecipientChip.tsx
  • src/components/mail/composeMessageDialog/components/DefaultAttachmentItem.tsx
  • src/components/mail/composeMessageDialog/components/RecipientInput.tsx
  • src/components/mail/composeMessageDialog/components/RichTextEditor.tsx
  • src/components/mail/composeMessageDialog/components/editorBar/EditorBarButton.tsx
  • src/components/mail/composeMessageDialog/components/editorBar/EditorBarGroup.tsx
  • src/components/mail/composeMessageDialog/components/editorBar/index.tsx
  • src/components/mail/composeMessageDialog/components/fontSizeExtension.ts
  • src/components/mail/composeMessageDialog/index.tsx
  • src/components/mail/composeMessageDialog/types/index.ts
  • src/components/mail/sidenav/index.tsx
  • src/features/mail/MailView.tsx
  • src/features/mail/components/header/index.tsx
  • src/features/mail/components/searchInput/index.tsx
  • src/features/mail/components/trayEmptyState/index.tsx
  • src/hooks/navigation/useSidenavNavigation.tsx
  • src/i18n/locales/en.json
  • src/index.css
  • src/routes/layouts/SidebarAndHeaderLayout.tsx
  • src/routes/paths/index.ts
  • src/types/mail/index.ts
  • src/types/prettysize.d.ts
  • src/utils/bytesToString.test.ts
  • src/utils/bytesToString.ts
  • src/utils/bytesToString/bytesToString.test.ts
  • src/utils/bytesToString/index.ts
💤 Files with no reviewable changes (12)
  • src/utils/bytesToString.ts
  • src/components/mail/composeMessageDialog/components/editorBar/EditorBarButton.tsx
  • src/components/mail/composeMessageDialog/components/editorBar/EditorBarGroup.tsx
  • src/components/mail/composeMessageDialog/index.tsx
  • src/components/mail/composeMessageDialog/components/RecipientInput.tsx
  • src/components/mail/composeMessageDialog/components/RichTextEditor.tsx
  • src/components/mail/composeMessageDialog/types/index.ts
  • src/components/mail/composeMessageDialog/components/DefaultAttachmentItem.tsx
  • src/components/mail/composeMessageDialog/components/fontSizeExtension.ts
  • src/components/mail/composeMessageDialog/components/editorBar/index.tsx
  • src/utils/bytesToString.test.ts
  • src/components/chips/RecipientChip.tsx

@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.coderabbit.yaml (1)

11-20: ⚠️ Potential issue | 🟠 Major

Los path_instructions.path con coma pueden dejar reglas sin aplicarse.

Ahora mismo cada path mezcla dos globs en una sola cadena. Separarlos evita que las instrucciones queden inactivas por patrón no coincidente.

🔧 Propuesta de ajuste
   path_instructions:
-    - path: '**/*.ts,**/*.tsx'
+    - path: '**/*.ts'
       instructions: |
         Review the TypeScript/React code for:
         - Possible bugs and unhandled edge cases
         - Performance issues and unnecessary re-renders
         - Type safety improvements
         - Clean code principles and readability
         - Security vulnerabilities
-    - path: '**/*.test.ts,**/*.test.tsx'
+    - path: '**/*.tsx'
+      instructions: |
+        Review the TypeScript/React code for:
+        - Possible bugs and unhandled edge cases
+        - Performance issues and unnecessary re-renders
+        - Type safety improvements
+        - Clean code principles and readability
+        - Security vulnerabilities
+    - path: '**/*.test.ts'
+      instructions: |
+        Review tests for:
+        - Missing edge case coverage
+        - Proper assertion usage
+        - Test isolation and mocking correctness
+    - path: '**/*.test.tsx'
       instructions: |
         Review tests for:
         - Missing edge case coverage
         - Proper assertion usage
         - Test isolation and mocking correctness
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.coderabbit.yaml around lines 11 - 20, El problema es que la clave path en
la sección de path_instructions contiene dos globs combinados en una sola cadena
('**/*.ts,**/*.tsx'), lo que puede dejar una de las reglas sin aplicarse;
actualiza la configuración para separar los globs en elementos distintos (por
ejemplo como un array de paths o como entradas separadas) y asegurarte de que
cada entrada mantenga su bloque instructions; revisa y corregir las apariciones
de path_instructions.path y la sección que hoy tiene
'**/*.test.ts,**/*.test.tsx' para que cada patrón sea independiente y las
instrucciones asociadas se ejecuten correctamente.
♻️ Duplicate comments (2)
src/features/mail/components/searchInput/index.tsx (1)

55-77: ⚠️ Potential issue | 🟠 Major

El “clear” no limpia el campo: falta value controlado y handler de click.

En Line 76 se muestra el icono, pero no ejecuta ninguna limpieza; además el input no está ligado a query, así que el estado no puede resetear el texto visible.

🔧 Propuesta de corrección
         <input
           ref={searchInput}
           id="globalSearchInput"
           data-cy="globalSearchInput"
           autoComplete="off"
           spellCheck="false"
           type="text"
+          value={query}
           className="inxt-input left-icon h-10 w-full appearance-none rounded-lg border border-transparent bg-gray-5 px-9 text-lg text-gray-100 placeholder-gray-60 outline-none ring-1 ring-gray-10 transition-all duration-150 ease-out hover:shadow-sm hover:ring-gray-20 focus:border-primary focus:bg-surface focus:placeholder-gray-80 focus:shadow-none focus:ring-3 focus:ring-primary/10 dark:focus:bg-gray-1 dark:focus:ring-primary/20"
           onKeyUpCapture={(e) => {
             if (e.key === 'Escape') {
               e.currentTarget.blur();
             }
           }}
           onChange={(e) => setQuery(e.target.value)}
@@
-        <XIcon className={getClearButtonClassName(query, openSearchBox)} size={20} />
+        <XIcon
+          className={getClearButtonClassName(query, openSearchBox)}
+          size={20}
+          onClick={() => {
+            setQuery('');
+            searchInput.current?.focus();
+          }}
+        />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/components/searchInput/index.tsx` around lines 55 - 77, The
clear icon doesn't reset the visible text because the input isn't controlled and
the XIcon has no click handler; update the input JSX to bind value={query} so it
reflects state (searchInput ref and setQuery remain unchanged), and add an
onClick handler to the XIcon (referencing XIcon and getClearButtonClassName)
that calls setQuery('') and then either focuses searchInput.current.focus() or
blurs it per desired UX; also make the XIcon accessible by adding an appropriate
aria-label/role or wrapping it in a button element so keyboard users can trigger
the clear action.
src/features/mail/components/header/index.tsx (1)

61-61: ⚠️ Potential issue | 🟡 Minor

El Checkbox sigue sin nombre accesible.

Añade aria-label o una etiqueta asociada para lectores de pantalla.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/mail/components/header/index.tsx` at line 61, El Checkbox en el
componente header (renderizado como <Checkbox />) carece de nombre accesible;
actualiza la instancia de Checkbox para proporcionar un nombre visible para
lectores de pantalla añadiendo un atributo aria-label (por ejemplo
aria-label="Seleccionar todos los mensajes") o envolviéndolo con una etiqueta
<label> asociada, asegurándote de usar la prop correcta del componente Checkbox
si es de una librería (p. ej. ariaLabel, aria-label, label) y mantener el texto
claro y localizado; modifica la línea donde se renderiza Checkbox para pasar esa
prop o agregar el label asociado.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/features/mail/components/header/index.tsx`:
- Around line 13-51: The menu items in listActionContext and bulkActionContext
have no-op actions (action: () => {}) so selecting them does nothing; replace
those no-ops with calls to the real filter and bulk-action handlers used by the
mail feature (e.g., invoke the component prop or context methods that apply
filters and perform bulk operations). Specifically, update listActionContext
items to call the existing filter handler (e.g., props.onFilter or
mailStore.applyFilter) with the appropriate filter keys like
'all'|'none'|'read'|'unread'|'starred'|'unstarred', and update bulkActionContext
items to call the bulk handlers (e.g., props.onBulkAction or
mailService.trashAll/mailService.archiveAll) instead of empty functions; ensure
the actions also close the menu and update component state or dispatch events as
the rest of the header component expects (refer to listActionContext,
bulkActionContext, MenuItemType, translate, TrashIcon, ArchiveIcon to locate and
wire the calls).

---

Outside diff comments:
In @.coderabbit.yaml:
- Around line 11-20: El problema es que la clave path en la sección de
path_instructions contiene dos globs combinados en una sola cadena
('**/*.ts,**/*.tsx'), lo que puede dejar una de las reglas sin aplicarse;
actualiza la configuración para separar los globs en elementos distintos (por
ejemplo como un array de paths o como entradas separadas) y asegurarte de que
cada entrada mantenga su bloque instructions; revisa y corregir las apariciones
de path_instructions.path y la sección que hoy tiene
'**/*.test.ts,**/*.test.tsx' para que cada patrón sea independiente y las
instrucciones asociadas se ejecuten correctamente.

---

Duplicate comments:
In `@src/features/mail/components/header/index.tsx`:
- Line 61: El Checkbox en el componente header (renderizado como <Checkbox />)
carece de nombre accesible; actualiza la instancia de Checkbox para proporcionar
un nombre visible para lectores de pantalla añadiendo un atributo aria-label
(por ejemplo aria-label="Seleccionar todos los mensajes") o envolviéndolo con
una etiqueta <label> asociada, asegurándote de usar la prop correcta del
componente Checkbox si es de una librería (p. ej. ariaLabel, aria-label, label)
y mantener el texto claro y localizado; modifica la línea donde se renderiza
Checkbox para pasar esa prop o agregar el label asociado.

In `@src/features/mail/components/searchInput/index.tsx`:
- Around line 55-77: The clear icon doesn't reset the visible text because the
input isn't controlled and the XIcon has no click handler; update the input JSX
to bind value={query} so it reflects state (searchInput ref and setQuery remain
unchanged), and add an onClick handler to the XIcon (referencing XIcon and
getClearButtonClassName) that calls setQuery('') and then either focuses
searchInput.current.focus() or blurs it per desired UX; also make the XIcon
accessible by adding an appropriate aria-label/role or wrapping it in a button
element so keyboard users can trigger the clear action.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a17d4d90-32ac-469f-bf1c-72ffc5964bf4

📥 Commits

Reviewing files that changed from the base of the PR and between 6bfaafa and 48cd15b.

📒 Files selected for processing (7)
  • .coderabbit.yaml
  • src/features/mail/components/header/index.tsx
  • src/features/mail/components/searchInput/index.tsx
  • src/features/mail/components/trayEmptyState/index.tsx
  • src/i18n/locales/en.json
  • src/routes/layouts/SidebarAndHeaderLayout.tsx
  • src/types/mail/index.ts

@xabg2
Copy link
Contributor Author

xabg2 commented Mar 18, 2026

Ready for review @larryrider

@xabg2 xabg2 merged commit b8ba395 into master Mar 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants