Skip to content

Repository files navigation

🌟 Karomia - Frontend Challenge 🌟

1. Introduction

This project represents my solution for the Karomia Frontend Challenge, focusing on implementing an in-line tagging system within a rich text editor. The goal is to allow users to easily see which parts of the text link to specific data points by tagging arbitrary ranges and highlighting text based on selected tags.

This solution utilizes React for the frontend framework (overlayed with a Karomia UI sauce), Tiptap for the rich text editor, Jotai for state management, and React Aria Components for accessible UI elements.

2. Functional Overview

This section details each implemented feature with explanations and visual aids.

2.1. Persistence with Local Storage

To ensure that the user's tags and editor content are preserved across browser sessions, this application utilizes localStorage in conjunction with Jotai's atomWithStorage.

  • Tags: The list of created tags (including their name, color, ID, active state) is automatically saved to localStorage under the key karomia_tags whenever a tag is added or deleted. On subsequent visits, the application loads these tags from localStorage into the global state.

  • Editor Content: The entire content of the rich text editor, including any applied tags as marks, is also automatically saved to localStorage under the key karomia_editor_content whenever the content changes.

2.2. Fetching and Rendering Markdown

When the application starts, it first checks if there is any saved editor content in localStorage. If content is found, it is loaded directly into the editor. If no saved content exists, the application proceeds to fetch the initial Markdown content from the mocked API (using React Query hook). This Markdown is then converted to HTML using the marked library and rendered within the Tiptap editor.

2.3. Responsive Design

On smaller viewports, the TagList is initially hidden behind a hamburger menu in the top right of the navigation bar. Clicking the hamburger icon slides the TagList into view from the right.

Also, the editor toolbar is moved to the bottom on the smallest viewports.

2.4. Basic Text Formatting in Tiptap

The Tiptap editor supports basic text formatting options such as bold, italic, headings, lists, and text alignment, accessible via a custom toolbar.

2.5. Text Selection and "+ New Tag" Button

When the user selects a portion of text in the editor, an icon button (to manage tags for the currently selected text) appears via a BubbleMenu.

2.5. Assigning Tags

2.5.1. Creating New Tags

Clicking the icon button reveals a form within the BubbleMenu where users can:

  • Specify a tag name/label.
  • Pick a tag color using a color picker.

Users can then click an "Add" button to create the tag and assign it to the selected text.

2.5.2. Applying Existing Tags

The BubbleMenu also displays a list of existing tags (from the Jotai store) using a ListBox from React Aria. Users can click on a tag in the list to apply it to the currently selected text.

This list also displays the active tags for the currently selected text. So, when clicking an active tag, it will remove this tag from the selection as well.

2.6. Overlappping and Visual Distinction for Tagged Text

Tagged segments of text are visually distinguished in the editor by a background color and a bottom border, both derived from the tag's color. Overlapping tags are also visually represented by using stacked backgrounds with opacity.

2.7. Tag List

A TagList component is displayed next to the editor, showing all created tags (sorted alphabetically) with their name, color (as a swatch), and the number of times they are used in the editor. It also displays the number of tags in the title.

2.8. Highlighting Tagged Text

Each tag in the TagList has a "Highlight" button. Clicking this button highlights all occurrences of that tag in the editor. Clicking again toggles the highlighting off.

2.9. Deleting Tags

Each tag in the TagList also has a "Delete" button. Clicking it removes the tag from the store and all its associated marks from the editor content.

2.10. Clear Tags

A "Clear" icon button is available in the TagList to clear all tags. Clicking it removes all tags from the store and all its associated marks from the editor content.

Technologies Used

  • Frontend:

    • React: for building the user interface.
    • React Aria Components: for accessible and unstyled UI components.
    • CSS modules: for scoped styling of components with SASS.
    • React Hook Form: for form management and validation.
    • Zod: for schema validation.
    • Axios + React Query: for making HTTP requests to the backend.
    • react-error-boundary: for handling uncaught errors during rendering.
    • svgr: transforming SVG into React components for ease of use.
  • Backend:

    • Node.js: for the server-side runtime environment.
    • Express.js: for building the REST API.
    • Multer: for handling file uploads.
    • Pinecone: for the vector database.
    • LangChain: for interacting with LLMs (OpenAI / Hugging Face) and generating embeddings.
    • dotenv: for managing environment variables.
    • cors: For handling Cross-Origin Resource Sharing.
    • uuid: For generating unique identifiers.

3. Technical Overview

β”œβ”€β”€ public                      # Contains static assets served by Vite.
β”œβ”€β”€ src
β”‚Β  Β β”œβ”€β”€ @tiptap                 # Contains internal UI components, hooks, styles and logic specifically tailored for the Tiptap editor.
β”‚Β  Β β”œβ”€β”€ assets
β”‚Β  Β β”‚Β   └── icons               # SVG icons used throughout the application.
β”‚Β  Β β”‚Β   └── images              # Raster images used in the application (e.g., logo, empty state).
β”‚Β  Β β”œβ”€β”€ components
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ app                 # The main application component.
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ bubble-menu         # Components related to the Tiptap bubble menu for tagging.
β”‚Β  Β β”‚Β  Β β”‚Β  Β β”œβ”€β”€ bubble-menu-form      # Component for the tag creation form within the bubble menu.
β”‚Β  Β β”‚Β  Β β”‚Β   └── bubble-menu-tag-list  # Component for the list of existing tags within the bubble menu.
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ nav-bar             # The application's navigation bar component.
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ tag-list            # Component displaying the list of all tags.
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ tagging             # Container component for the editor and tag list.
β”‚Β  Β β”‚Β  Β β”œβ”€β”€ tiptap              # Specific components for the Tiptap editor.
β”‚Β  Β β”‚Β   └── ui                  # Smaller, reusable UI primitives (buttons, color picker, etc.).
β”‚Β  Β β”œβ”€β”€ constants               # Application-wide constants (e.g., event names, query keys).
β”‚Β  Β β”œβ”€β”€ extensions              # Custom Tiptap extensions (for tagging functionality).
β”‚Β  Β β”œβ”€β”€ hooks                   # Custom React hooks for various functionalities (API fetching, editor interactions).
β”‚Β  Β β”œβ”€β”€ mocks                   # Mocked data for API responses.
β”‚Β  Β β”œβ”€β”€ stores                  # Jotai store for managing application state.
β”‚Β  Β β”œβ”€β”€ styles                  # Global and shared SCSS styles for the application.
β”‚Β  Β β”œβ”€β”€ types                   # TypeScript type definitions for data structures.
β”‚Β  Β β”œβ”€β”€ utils                   # Utility functions (event bus, Markdown parsing, etc.).
β”‚Β   └── index.tsx               # Entry point of the React application.
β”œβ”€β”€ eslint.config.js         # ESLint configuration file.
β”œβ”€β”€ index.html               # Main HTML entry point.
β”œβ”€β”€ package-lock.json        # npm lock file for dependency management.
β”œβ”€β”€ package.json             # npm package definition file.
β”œβ”€β”€ README.md                # Documentation for the project.
β”œβ”€β”€ tsconfig.app.json        # TypeScript configuration for the application.
β”œβ”€β”€ tsconfig.json            # Main TypeScript configuration file.
β”œβ”€β”€ vite-env.d.ts            # TypeScript environment declaration file for Vite.
└── vite.config.ts           # Vite build configuration file.

3.2. Used Packages

  • React (react, react-dom): Frontend framework for building the UI.
  • Tiptap (@tiptap/react, @tiptap/starter-kit, @tiptap/extension-html, @tiptap/pm): Rich text editor component and its core ProseMirror utilities.
  • Tiptap Extensions (@tiptap/extension-highlight, @tiptap/extension-image, @tiptap/extension-link, @tiptap/extension-subscript, @tiptap/extension-superscript, @tiptap/extension-task-item, @tiptap/extension-task-list, @tiptap/extension-text-align, @tiptap/extension-typography, @tiptap/extension-underline): Additional Tiptap extensions for various functionalities.
  • Jotai (jotai): Minimalist state management library.
  • React Aria Components (react-aria-components): Library for building accessible UI components.
  • React Hook Form (react-hook-form, @hookform/resolvers): Library for form management and validation.
  • Zod (zod): Schema declaration and validation library.
  • Marked (marked): Library for converting Markdown to HTML.
  • UUID (uuid): Library for generating unique IDs for tags.
  • Classnames (classnames): Utility for conditionally joining CSS class names.
  • TanStack Query (@tanstack/react-query): Library for fetching and managing asynchronous data (mocked API data).
  • Normalize.css (normalize.css): CSS reset library for consistent styling across browsers.
  • Floating UI (@floating-ui/react): Library for positioning floating elements like the BubbleMenu.

3.3. State Management

  • Jotai is used for managing the global application state, including:
    • The list of tags (tagsAtom).
    • The ID of the currently highlighted tag (highlightedTagIdAtom).
    • The editor content (editorContentAtom).

3.4. Tiptap Configuration

  • The Tiptap editor is initialized with the StarterKit for basic text formatting and a custom Tagger extension to handle the tagging logic.
  • A BubbleMenu is used to display the tag creation form and existing tags near the text selection.
  • A custom toolbar provides access to basic formatting commands.

3.5. Custom Tiptap Extension (Tagger)

  • Defines a TagMark to represent tagged text in the editor. This manages the data-active, data-tag-id, data-tag-name, and data-tag-color attributes on the tagged span elements.
  • Adds commands (applyTag, deleteTags, removeTag, highlightTag) to interact with tags in the editor.

3.6. Event Bus

  • A simple event bus facilitates communication between different parts of the application, such as notifying the editor when a new tag is created.

3.7. Responsive Design

  • CSS media queries are used to adjust the layout for different screen sizes.
  • On mobile, the TagList is hidden behind a hamburger menu and the toolbar is moved to the bottom.

4. How to Install, Start, and Test

4.1. Installation

  1. Clone the repository:
    git clone https://github.com/wesleymostien/karomia-tagging-app
    cd karomia-tagging-app
  2. Install dependencies:
    npm install

4.2. Starting the Application

  1. Run the development server:
    npm run dev

4.3. Viewing the Application

Open your browser (tested with Google Chrome) on http://localhost:5173/.

About

Karomia - Frontend Challenge

Resources

Stars

0 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages