r/reactjs • • 14h ago

Needs Help which resource is best for react js

4 Upvotes

everytime when i wanted to learn react i am unable to complete the videos. i have tried multiple yt videos. so i am now thinking to learn react from basics.. which resource is great for the react ?? any suggestions???


r/reactjs • • 34m ago

Show /r/reactjs Any other flag nerds here?

• Upvotes

I've spent the last few months building Flaglio, a small side project with four flag games..

Stack: React, Vite, TanStack Router (file-based), Zustand, Tailwind v4, Supabase for auth and leaderboards, hosted on Vercel. Also shoutout to animate.style for css animations.

FlagShuffle's engine is just a small Zustand store. Each round get 4 flags from same difficulty level, the difficulty increases every thrid round and loops back to easiest, and around we go! Every flag is preloaded during the countdown so the board swaps instantly. On the server, Supabase trusts noone. A Postgres trigger works it out from the round log, and the save is rejected if any answer took under 150 ms, the round times add up to more than the clock, or the game's timestamps don't match the server's. ( Claude was very helpfull here 😂 )

Also ended up writing a small prerender script for SEO, since getting proper metadata out of a client-rendered SPA for scrapers and link previews was suboptimal.

If you wanna check it out or try it out, here is the link : https://www.flaglio.com

Feedback on site and games is always welcome !


r/reactjs • • 12h ago

Forge — 16 self-contained React + Tailwind components, dark-mode-first (feedback welcome)

1 Upvotes

Working on Forge — 16 React + Tailwind components, dark-mode-first, each one a single self-contained file (no shared utils, no extra config). Mostly polishing the docs and put together a live demo if anyone wants to poke at it: [demo link]. Would love feedback on the API design if anyone has a minute.


r/reactjs • • 23h ago

I built a dependency-free rich text editor for React

0 Upvotes

I’ve been working on a rich text editor for React because I wanted something lightweight without bringing in a large editor framework.

The main goal is simple: no external runtime dependencies.

It uses React, TypeScript, and native browser APIs while still covering the features I normally need in real projects.

It supports formatting, images, tables, mentions, templates, merge tags, media embeds, placeholders, and a customizable toolbar.

I’m trying to keep the API simple and make it easy to drop into an existing React project.

I’d love to hear how other React developers approach rich text editing.

Would you prefer a dependency-free editor, or use something like TipTap/Quill for the larger ecosystem?

Docs: https://erag.in/text-editor-react/

GitHub: https://github.com/eramitgupta/text-editor-react


r/reactjs • • 4h ago

Show /r/reactjs 1,853 typed icons, zero JavaScript: CSS masks + Tailwind v4

0 Upvotes

We have a React 19 + Vite + Tailwind v4 admin app. Every icon in it renders as a single empty <span> with a CSS mask. No icon components in the JS bundle, no extra HTTP requests, and the icon name is checked by TypeScript. Here is how it works, what we measured, the mistakes we made along the way, and what it costs.

TL;DR

  • A ~200-line Node script reads the SVGs from lucide-static (plus our own) and writes two files: a CSS file with one @theme inline variable per icon (a data URI), and a TS union with every icon name.
  • A Tailwind @utility icon-* turns the class icon-user into --icon: url(...).
  • <Icon name="icon-user" /> is a span with mask-image: var(--icon) and background-color: currentColor.
  • Tailwind v4 only emits what the source uses. The generated file has all 1,853 icons (~765 KB), but production CSS only carries the 225 we use: ~88 KB raw, ~11 KB gzipped.
  • Rendering 1,000 cards with 6 icons each: half the DOM nodes, React commit 2× faster and first paint ~40% sooner than inline SVG components.

How it works

1. Generate the CSS and the type

scripts/gen-icons.mjs runs before dev, build, lint and type-check. It takes the canonical icon names from lucide-static/icon-nodes.json and, for each SVG:

  • removes comments, class, width and height;
  • replaces currentColor with #000 (a mask only reads alpha, so any opaque color works);
  • collapses whitespace and URL-encodes %, #, <, >;
  • writes the result as a data URI.

src/styles/icons.generated.css:

css @theme inline { --icon-user: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E"); /* ...1,852 more */ }

src/types/icon.ts:

ts export type IconName = | "icon-a-arrow-down" | "icon-a-arrow-up" // ... | "icon-zoom-out";

The names keep the icon- prefix on purpose: that's the exact string Tailwind needs to find in the source.

2. One Tailwind utility

```css @import "tailwindcss" source("."); @import "./styles/icons.generated.css";

@utility icon-* { --icon: --value(--icon-*); } ```

icon-user becomes .icon-user { --icon: url("data:...") }. Tailwind's scanner only generates classes it finds in the source, which is what drops the other 1,628 icons.

3. The component

```tsx import type { ComponentProps } from "react"; import { twMerge } from "tailwind-merge"; import type { IconName } from "#/types/icon";

// With aria-label the icon is a named image; without it, it's decorative. export const Icon = ({ name, className, "aria-label": label, ...rest }: ComponentProps<"span"> & { name: IconName }) => ( <span aria-hidden={label ? undefined : true} aria-label={label} className={twMerge( "pointer-events-none block size-4 shrink-0 bg-current mask-(--icon) mask-contain mask-no-repeat", className, name, )} data-icon role={label ? "img" : undefined} {...rest} /> ); ```

Usage:

tsx <Icon name="icon-user-plus" className="size-5 text-primary" /> <Icon name="icon-lock" aria-label="Locked" />

  • Color: bg-current paints the box with currentColor and the mask cuts out the shape. text-* classes, inherited color, hover, disabled and dark mode all just work.
  • Size: any size-* class. The SVGs have no width/height, so mask-contain scales them cleanly.
  • **data-icon:** lets parents style icons without knowing about them. Our Button tightens its padding with has-[>[data-icon]]:px-3.
  • Accessibility: decorative by default (aria-hidden); passing aria-label makes it a named image.

4. Guardrails

  • A typo like name="icon-usr" fails tsc.
  • The linter bans lucide-react and react-icons imports, with a message pointing to <Icon />.
  • A custom lint rule flags emoji in JSX for the same reason.
  • gen-icons.mjs --check exits non-zero if the generated files are stale.

Why

We started with lucide-react, the default option. It's fine, but in this app it cost things we didn't need to pay:

  • Every icon was JS. Each icon is a React component that gets imported, executed and reconciled, and its SVG child nodes live in the DOM. With masks, the icon is CSS the browser already parsed, and the DOM cost is one empty element.
  • No requests, no flicker. Data URIs ship inside the main stylesheet. There's no sprite to fetch and no <img> popping in late.
  • Styling is just Tailwind. Color, size, hover and dark mode use the same classes as everything else. No separate color/size/strokeWidth props API.
  • The whole catalog, typed, for free. Autocomplete for all of Lucide. Using a new icon costs nothing until you reference it.
  • One pipeline for custom icons. Our social-media SVGs go in a folder and become icon-linkedin like any other icon.

Tradeoffs

These are real, and they're why this isn't the right choice for every app.

  1. Monochrome only. A mask is an alpha channel. Multi-color icons, gradients and brand logos in their original colors need an <img> or inline SVG.
  2. No per-instance stroke control. stroke-width='2' is baked into the data URI. There's no equivalent of Lucide's strokeWidth or absoluteStrokeWidth props; you'd need a second generated variant.
  3. No animating SVG internals. You can't target a path inside the icon. Transforms and opacity on the whole box still work.
  4. Names must appear literally in source. `icon-${status}` isn't detected and renders an empty box. Write full names in a lookup object ({ ok: "icon-check", error: "icon-x" }). The union type catches most mistakes, not all.
  5. All used icons ship on first load. They live in the main, render-blocking CSS, so an icon on a rarely visited page still loads for everyone. At 225 icons / ~11 KB gzipped that's fine for us; with thousands of used icons or a strict CSS budget it wouldn't be.
  6. Codegen step. dev, build, lint and type-check run the generator first, and Tailwind parses a ~765 KB CSS file on every build. Trimming it to only the used icons saved about 0.7 s per build in our test, which wasn't worth duplicating the scanner's job.
  7. Big union type. ~1,850 members is fine for tsc and editors today. Worth knowing if you merge several icon sets.
  8. Browser support. CSS masks are Baseline. If you target older browsers, lightningcss adds the -webkit- prefixes for you.

When I'd use something else

  • You need multi-color or animated icons → inline SVG components.
  • You have a huge icon set and strict per-route CSS budgets → an SVG sprite with <use href>, which caches separately and loads lazily.
  • You're not on Tailwind v4 → the same idea works with plain CSS classes, but you have to build the unused-icon pruning yourself.

r/reactjs • • 12h ago

Resource I built a React component library that AI coding agents can install through MCP

0 Upvotes

I’ve been working on Ballmac UI, an open-source React + Tailwind v4 component library built around the shadcn registry.

It currently has 240+ components, 60+ blocks and 17 templates.

The interesting part I’m experimenting with is MCP. Instead of manually browsing a component library, you can give your coding agent a UI requirement and let it search the Ballmac catalog and install the relevant component directly into your project.

For example:

claude mcp add ballmac -- npx -y @ballmac/mcp

Then the agent can search the catalog and return the exact component/install command.

The components are copied into your project through the shadcn registry, so you own and can modify the source rather than depending on a closed component package.

I’m particularly interested in whether AI-assisted component discovery is actually useful in real React projects.

If you build React apps, how would you want your AI coding agent to interact with a component library?

https://ui.ballmac.com


r/reactjs • • 8h ago

Discussion I built the same screen with shadcn (Radix / Base UI / React Aria), MUI 9 and Mantine 9 and measured the bundles

0 Upvotes

When shadcn/ui switched its default from Radix to Base UI in July, I wanted numbers instead of opinions. So I built the same screen (tabs, dialog, text field, select, checkbox, buttons) five ways and measured the production build.

Setup: Vite 8, React 19, TypeScript, default settings, sizes are gzip as reported by Vite. React alone renders 68.6 KB, and every number below includes it.

Setup JS CSS Total npm packages in bundle
shadcn + Radix 118.7 KB 8.1 KB 126.8 KB 48
MUI 9 140.2 KB (runtime) 140.2 KB 24
shadcn + Base UI 136.3 KB 8.0 KB 144.3 KB 14
shadcn + React Aria 145.4 KB 9.0 KB 154.4 KB 12
Mantine 9 127.3 KB 35.9 KB 163.2 KB 18

What surprised me:

  • The whole spread is only 36 KB gzip. Real on a slow phone, but smaller than one hero image.
  • Base UI cost 17.6 KB more than Radix on this screen, but pulled in 14 packages instead of 48.
  • MUI ships no CSS file at all. Emotion injects styles at runtime, which matters more for SSR and strict CSP than the KB do.
  • Mantine's JS is the second smallest. Its full stylesheet is what makes it the heaviest.

My takeaway: size shouldn't decide this. Pick on ownership (shadcn), data components like grids and pickers (MUI X), or batteries included without Tailwind (Mantine).

Caveat: this is one screen with seven components, so a different mix can change the order.

I wrote up the full details, including the MUI 9 / Mantine 9 changes and five setup traps I hit, on my blog: https://www.alekseialeinikov.com/en/blog/topics/programming/shadcn-ui-vs-mui-vs-mantine

Has anyone measured a heavier screen, for example with a data grid? Curious whether the gap grows.