Coder Social home page Coder Social logo

gregberge / twc Goto Github PK

View Code? Open in Web Editor NEW
1.3K 6.0 25.0 1.69 MB

Create reusable React + Tailwind CSS components in one line ✨

Home Page: https://react-twc.vercel.app

License: MIT License

TypeScript 43.63% JavaScript 16.74% MDX 39.30% CSS 0.33%
react styled-components tailwindcss

twc's Introduction

TWC — Supercharge React + Tailwind CSS


TWC creates reusable React + Tailwind CSS components in one line

Features

  • ⚡️ Lightweight — only 0.49kb
  • ✨ Autocompletion in all editors
  • 🎨 Adapt the style based on props
  • ♻️ Reuse classes with asChild prop
  • 🦄 Work with all components
  • 😎 Compatible with React Server Components
  • 🚀 First-class tailwind-merge and cva support

Documentation

Visit our official documentation.

Usage

Without twc:

import * as React from "react";

const Card = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={clsx(
      "rounded-lg border bg-slate-100 text-white shadow-sm",
      className,
    )}
    {...props}
  />
));

With twc:

import { twc } from "react-twc";

const Card = twc.div`rounded-lg border bg-slate-100 text-white shadow-sm`;

Contributing

Feel like contributing? That's awesome! We have a contributing guide to help guide you.

Want to help improve the docs?

The docsite lives in the monorepo.

If you're interested in contributing to the documentation, check out the contributing guide.

Support

Having trouble? Ping me on X

Acknowledgement

The development of TWC was only possible due to the inspiration and ideas from these amazing projects.

License

MIT License © 2023-Present Greg Bergé

twc's People

Contributors

aarvay avatar callumk7 avatar clarencepenz avatar emmanuelchucks avatar erikshestopal avatar gabrielelpidio avatar gregberge avatar hyoban avatar jprisk avatar koichikiyokawa avatar simonecervini avatar twhitbeck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

twc's Issues

twc(SomeRadixComponent) => asChild won't work as expect

🐛 Bug Report

twc(SomeRadixComponent)`` component => asChild won't work as expect

To Reproduce

const HoverCardContent = twc(
  HoverCard.Content
)`data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] rounded-md bg-white p-5 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] data-[state=open]:transition-all`

const Hover = () => {
  ...
  return (
    ...
    <HoverCardContent
      className="bg-cyan-200 w-[300px] h-[300px]"
      sideOffset={5}
      asChild
    >
      {/* hover card won't work */}
      <div>
         ....
      </div>
    </HoverCardContent>
    ...
  )
}

Expected behavior

should work with radix components

Link to repl or repo (highly encouraged)

https://codesandbox.io/p/devbox/react-twc-hover-card-9t6tzc

Run npx envinfo --system --binaries --npmPackages twc,react,react-dom --markdown --clipboard

Paste the results here:

## System:
 - OS: macOS 14.1.1
 - CPU: (8) arm64 Apple M1
 - Memory: 84.41 MB / 8.00 GB
 - Shell: 5.9 - /bin/zsh
## Binaries:
 - Node: 18.18.2 - ~/.nvm/versions/node/v18.18.2/bin/node
 - Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.2/bin/yarn
 - npm: 9.8.1 - ~/.nvm/versions/node/v18.18.2/bin/npm
 - pnpm: 7.30.0 - ~/.nvm/versions/node/v18.18.2/bin/pnpm
## npmPackages:
 - react: ^18.2.0 => 18.2.0 
 - react-dom: ^18.2.0 => 18.2.0 
 - react-twc: ^1.0.1 => 1.0.1 

Add ShouldForwardProp option to the twc function

🚀 Feature Proposal

Add ShouldForwardProp option to the twc function

Motivation

I don't want to use the prefixed props syntax

Example

twc.div(({ variant}) => buttonVariants({ variant} ) , (prop) => prop === "variant"))

Is it possible to use styled-components?

@gregberge I was thinking, is this project possible to use like we use styled-components?

For example:

const List = styled.ul`
  display: inline-block;

  & > li > a {
    color: red;
  }
`;

Twc?

const List = twc.ul`
  inline-block

  & > li > a {
    text-red-500
  }
`;

[Docs] Broken Link

🐛 Bug Report

Broken link on styling any component guide.

To Reproduce

Clicking on a link to "additional props" leads to a non-existing page.

Expected behavior

Link is supposed to direct to https://react-twc.vercel.app/docs/guides/additional-props but directs to https://react-twc.vercel.app/guides/additional-props.

When trying to make a PR for this issue, it seems that it works locally, so it is possible that the website is of an old build and the site hierarchy was changed.

Ways to improve the docs

I would probably do the research myself and make a PR if I had some time today but I don’t think I will be able to.

The website, it’s examples for things like as child and prop driven classes. The examples feel a little incomplete and I think I figured out why. Each example could use one more part demonstrating what the resulting output would be like. It would make more clear what asChild is doing, and how the props and classname objects can affect the output.

`react-twc` with `@radix-ui/react-accordion` - `collapsible` prop does not respect conditional `type="single"`

🐛 Bug Report

Hi! Thank you for this amazing lib,

I've encountered an issue when integrating react-twc with @radix-ui/react-accordion. According to the Radix Accordion documentation, the collapsible property should only be available when the type prop is set to single. However, it seems that this conditional logic is not being enforced when using react-twc to wrap the Accordion component.

Here's a snippet of how I'm using the library:

import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { twc } from "react-twc";

const Accordion = twc(AccordionPrimitive.Root)`py-2`;

export default function App() {
  return (
    <div className="App">
      {/* Should only allow `collapsible` when `type="single"` */}
      <Accordion type="single" collapsible>
                                 ^ here is type error
        {/* ... */}
      </Accordion>

      {/* Default usage without twc wrapper works as expected */}
      <AccordionPrimitive.Root type="single" collapsible>
        {/* ... */}
      </AccordionPrimitive.Root>
    </div>
  );
}

To Reproduce

CodeSandbox: https://codesandbox.io/p/sandbox/twc-radix-qz36h7

Expected behavior:

The collapsible prop should be conditional on the type prop being single, similar to how it works with the standard @radix-ui/react-accordion component usage.

Could you please look into this? It would be great to have react-twc enforce the same conditional prop logic as the original library or provide guidance on how to implement it.

Thank you for your assistance!

Metro encountered an error while trying to resolve react-twc

🐛 Bug Report

I ran into this issue when trying to use react-twc in an Expo app. I've temporarily copied the component into my project as a workaround. Seems we need either index.js to export dist/index or point "main" in package.json to dist/index.

image

To Reproduce

Use react-twc in an Expo project. My particular project is based off t3 turbo.

Expected behavior

It should work

## System:
 - OS: macOS 14.0
 - CPU: (12) arm64 Apple M2 Pro
 - Memory: 65.58 MB / 32.00 GB
 - Shell: 5.9 - /bin/zsh
## Binaries:
 - Node: 20.10.0 - ~/.volta/tools/image/node/20.10.0/bin/node
 - Yarn: 1.22.19 - ~/.volta/tools/image/yarn/1.22.19/bin/yarn
 - npm: 10.2.3 - ~/.volta/tools/image/node/20.10.0/bin/npm
 - pnpm: 8.6.3 - ~/.volta/tools/image/pnpm/8.6.3/bin/pnpm
 - bun: 1.0.25 - ~/.bun/bin/bun

Incorrect exports: Could not find a declaration file for module 'react-twc'

🐛 Bug Report

Could not find a declaration file for module 'react-twc'. 'stackblitz:/node_modules/react-twc/dist/index.mjs' implicitly has an 'any' type.
There are types at 'stackblitz:/node_modules/react-twc/dist/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'react-twc' library may need to update its package.json or typings.(7016)

image

To Reproduce

Install the library within a typescript project: Stackblitz

Expected behavior

To import the correct typings, it should be solved by changing the exports in the package.json

Link to repl or repo (highly encouraged)

Stackblitz

Run npx envinfo --system --binaries --npmPackages twc,react,react-dom --markdown --clipboard

Paste the results here:

## System:
 - OS: Linux 5.0 undefined
 - CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
 - Memory: 0 Bytes / 0 Bytes
 - Shell: 1.0 - /bin/jsh
## Binaries:
 - Node: 18.18.0 - /usr/local/bin/node
 - Yarn: 1.22.19 - /usr/local/bin/yarn
 - npm: 9.4.2 - /usr/local/bin/npm
 - pnpm: 8.10.5 - /usr/local/bin/pnpm
## npmPackages:
 - react: 18.2.0 => 18.2.0 
 - react-dom: 18.2.0 => 18.2.0

build failing

🐛 Bug Report

I am getting this error on the production build on Vercel and local too. Also, vscode shows a type not foud error with a red color line. I am using pnpm

./components/sidebar/tree.tsx:3:21
Type error: Cannot find module 'react-twc' or its corresponding type declarations.

  1 | 'use client';
  2 |
> 3 | import { twc } from 'react-twc';
    |                     ^
  4 | import { useRouter } from 'next/navigation';
  5 | import { TypeAnimation } from 'react-type-animation';
  6 | import { Trash, Edit } from 'lucide-react';
   Checking validity of types  . ELIFECYCLE  Command failed with exit code 1.
image

Paste the results here:

## System:
 - OS: macOS 14.1.1
 - CPU: (8) x64 Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
 - Memory: 293.66 MB / 8.00 GB
 - Shell: 5.9 - /bin/zsh
## Binaries:
 - Node: 21.5.0 - /usr/local/bin/node
 - Yarn: 1.22.15 - ~/.yarn/bin/yarn
 - npm: 6.14.9 - ~/.config/yarn/global/node_modules/.bin/npm
 - Watchman: 2021.10.18.00 - /usr/local/bin/watchman
## npmPackages:
 - react: 18.2.0 => 18.2.0 
 - react-dom: 18.2.0 => 18.2.0 

Incorrect CSS conflicts with Tailwind CSS IntelliSense extension

🐛 Bug Report

With Tailwind CSS IntelliSense extension installed, styles would be seen as conflicting with each other even though they are for separate components.

image

I am migrating from https://github.com/MathiasGilson/Tailwind-Styled-Component, it does not have this problem if it helps

To Reproduce

Steps to reproduce the behavior:

  1. follow https://react-twc.vercel.app/docs/getting-started to set up
  2. write 2 components with some overlapping style rules in one file

Expected behavior

They should not be seen as a CSSConclict

Customize `className` with props from underlying component `className` render function.

🚀 Feature Proposal

Some components from react-aria-components accept a function as className prop value. The function will receive the render props. So, it basically a render function for className. react-twc supports customizing className via props, might as well merge className render props from such components with the transient props. I use this pattern a lot while wrapping react-aria-components.

Motivation

To properly customize the produced className using the underlying className render props.

Example

Without react-twc:

import * as React from 'react'
import * as RAC from 'react-aria-components'
import { twMerge as tw } from 'tailwind-merge'

const Button = React.forwardRef(function Button({ className, ...props }, ref) {
    return ( 
        <RAC.Button 
            {...props} 
            className={(renderProps) => {
                return tw('flex px-2', typeof className === 'function' ? className(renderProps) : className)
            }
        } />
    )
})

With react-twc:

import * as RAC from 'react-aria-components'
import { twc } from 'react-twc'

const Button = twc(RAC.Button)(
    (props) => ['flex px-2', props.isHovered ? 'bg-blue-700' : 'bg-blue-600'], { asFunction: true }
)

Pitch

By supporting classname render function, react-twc will be fully compatible with component library such as react-aria-components and headlessui.

Unintended TS behaviour with asChild + cva usage?

If you use the cva pattern as documented you will get a TS error if you also try to pass asChild to the composed component (still does work though), i assume this not intended 🤔

// ts error if trying to use asChild with this Button
const Button = twc.button<ButtonProps>(({ variant }) => button({ variant }))

// doing this makes it work as expected
const Button = twc.button<ButtonProps & { asChild?: boolean }>(({ variant }) => button({ variant }))

edit: after checking how it works a little bit more it seems like using this generic is very unsafe, imo it doesnt really makes sense how it works rn:

const Div = twc.div<{test: boolean}>``;
// cannot even pass children
<Div test>
	<Anything/>
</Div>

in my opinion this generic should not work like this at all, i will attempt to fix this and explain my reasoning a little bit more in a pr and see if you like it

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.