twind icon indicating copy to clipboard operation
twind copied to clipboard

tw`bg-white` at use tw variable with template string it is not work!

Open Abdulrahmanelheyb opened this issue 2 years ago • 8 comments

I get an error: Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'StringLike'. Type 'TemplateStringsArray' is not assignable to type 'string'.

Abdulrahmanelheyb avatar Apr 29 '22 04:04 Abdulrahmanelheyb

Without some code it is difficult to help.

What twind version are you using?

sastan avatar Apr 29 '22 04:04 sastan

Without some code it is difficult to help.

What twind version are you using?

I using: "twind": "^1.0.0-next.37" and "@twind/with-next": "^1.0.0-next.37" for nextjs

Abdulrahmanelheyb avatar Apr 30 '22 05:04 Abdulrahmanelheyb

I get the error when using tw``without Parentheses, It is work fine when use with parentheses like this tw(``)

Abdulrahmanelheyb avatar Apr 30 '22 05:04 Abdulrahmanelheyb

tw accepts only a string: tw(„…“) or use tx that is an alias for tw(cx…) and works as template literal.

sastan avatar Apr 30 '22 17:04 sastan

In v0.16, tw took a template string.

https://twind.dev/api/interfaces/twind.tw.html#callable

The documentation for v1 migration says the following. It makes it sound like we can use it the same as we were in v0.16.

tw as known from twind v0.16

https://twind.style/docs/migration

The readme on GitHub says the same.

https://github.com/tw-in-js/twind/blob/next/website/pages/docs/migration.md#notable-changes

It looks like the equivalent of v0.16 tw is tx.bind(tw). That's not clear from the documentation. I found out about tx from the following reference page but it just says that it is shorthand for tw(cx(...args)). Coming from v0.16, it wasn't clear what cx does, so I didn't realize tx would get me the same behavior. I didn't make the connection until reading your comment on this issue.

https://twind.style/docs/reference#utilities

I think it would help if migration docs were updated to reflect that tx is the equivalent of v0.16 tw and that v1 tw is different.

Any insight into why the call signature of tw was changed in V1?

KyleJune avatar May 04 '22 06:05 KyleJune

In v0.16, tw took a template string.

twind.dev/api/interfaces/twind.tw.html#callable

The documentation for v1 migration says the following. It makes it sound like we can use it the same as we were in v0.16.

tw as known from twind v0.16

twind.style/docs/migration

The readme on GitHub says the same.

https://github.com/tw-in-js/twind/blob/next/website/pages/docs/migration.md#notable-changes

You are right that's a mistake in the docs.

It looks like the equivalent of v0.16 tw is tx.bind(tw). That's not clear from the documentation. I found out about tx from the following reference page but it just says that it is shorthand for tw(cx(...args)). Coming from v0.16, it wasn't clear what cx does, so I didn't realize tx would get me the same behavior. I didn't make the connection until reading your comment on this issue.

twind.style/docs/reference#utilities

I think it would help if migration docs were updated to reflect that tx is the equivalent of v0.16 tw and that v1 tw is different.

Yep. I must adjust this.

Any insight into why the call signature of tw was changed in V1?

The main reason is performance. Interpolating a template string array takes some time. By accepting only a string we can boost the performance for many cases (like transforming the class name attribute).

sastan avatar May 04 '22 07:05 sastan

The main reason is performance. Interpolating a template string array takes some time. By accepting only a string we can boost the performance for many cases (like transforming the class name attribute).

In that case, I've decided not to use tx. My main use case for tx was being able to have conditional classes. Below is an example.

<NavLink
  key={item.name}
  to={item.to}
  end
  className={({ isActive }) => tx`
    ${isActive
      ? "bg-gray-900 text-white"
      : "text-gray-300 hover:bg-gray-700 hover:text-white"}
    px-3 py-2 rounded-md text-sm font-medium
  `}
>
  {item.name}
</NavLink>

I decided to just make a thin wrapper around tw that allows it to take multiple arguments and will join them together with space separators. That way I can get the performance benefit of not interpolating a template string array but am still able to add conditional classes easily.

const _tw = twind.setup(twindConfig, sheet)
export const tw = (...tokens: string[]) => _tw(tokens.filter(Boolean).join(" "))

Below is what the NavLink looks like using my tw wrapper.

<NavLink
  key={item.name}
  to={item.to}
  end
  className={({ isActive }) => tw(
    isActive
      ? "bg-gray-900 text-white"
      : "text-gray-300 hover:bg-gray-700 hover:text-white",
    "px-3 py-2 rounded-md text-sm font-medium",
  )}
>
  {item.name}
</NavLink>

KyleJune avatar May 05 '22 01:05 KyleJune

@KyleJune You could use the style helper which provides a stitches like API. Docs are missing but here are the tests: https://github.com/tw-in-js/twind/blob/next/packages/twind/src/tests/style.test.ts#L61

import { style } from 'twind'

const navLinkStyle = style({
  label: 'NavLink', // optional
  // the classes to always use
  base: `px-3 py-2 rounded-md text-sm font-medium`,
  // only needed in cases there is no isActive in the props
  defaults: {
    isActive: false,
  },
  // define the props the navLinkStyle function accepts
  props: {
    isActive: {
      true: `bg-gray-900 text-white`,
      false:  `text-gray-300 hover:bg-gray-700 hover:text-white`,
    },
  },
})

// Usage
function Component({ item }) {
  return (<NavLink
    key={item.name}
    to={item.to}
    end
    className={navLinkStyle}
    // or explicit
    className={({ isActive }) => navLinkStyle({ isActive })}
  >
    {item.name}
  </NavLink>)

sastan avatar May 05 '22 07:05 sastan

Your example could use the builtin tx method. It does not need to be called as tagged template function.

<NavLink
  key={item.name}
  to={item.to}
  end
  className={({ isActive }) => tx(
    isActive
      ? "bg-gray-900 text-white"
      : "text-gray-300 hover:bg-gray-700 hover:text-white",
    "px-3 py-2 rounded-md text-sm font-medium",
  )}
>
  {item.name}
</NavLink>

or using an object:

<NavLink
  key={item.name}
  to={item.to}
  end
  className={({ isActive }) => tx({
      "bg-gray-900 text-white": isActive,
      "text-gray-300 hover:bg-gray-700 hover:text-white": !isActive,
    },
    "px-3 py-2 rounded-md text-sm font-medium"
 )}
>
  {item.name}
</NavLink>

sastan avatar Oct 04 '22 14:10 sastan