mathiasgilson / tailwind-styled-component Goto Github PK
View Code? Open in Web Editor NEWCreate Tailwind CSS React components like styled components with class names on multiple lines and conditional class rendering
License: MIT License
Create Tailwind CSS React components like styled components with class names on multiple lines and conditional class rendering
License: MIT License
Hey guys, thanks for the awesome library.
I noticed there is no way to pass tw an Element to wrap on the fly.
in styled-components I think you could do it with:
const StyledComponent = styled.div``
StyledComponent.withComponent(OtherComponent)
Got any idea how to use tailwind-styled-component with a component that is decided on runtime?
Thank you!
First of all, trying this library, and loving it so far! ๐
I was trying to structure my code and attempting to create shared styling between components that fundamentally do not share same functionally.
To my knowledge; one could do this with styled components:
import { css } from 'styled-components';
const outlineStyle = css`
outline-width: 2px;
outline-style: 'solid';
outline-color: 'orange';
`
// Button.tsx
const Button = styled.button`
${outlineStyle}
`
const Input = styled.input`
${outlineStyle}
`
Basically, I think a wrapper css
-function exported from your library would be a great addition that is aware of tailwind-expressions.
${(props) => (props.dark ? `bg-theme-bgdark` : `bg-theme-bg`)}
${(props) => (props.color ? `${props.color}` : `text-theme-text`)}
The code above works perfectly fine but if I add one 1 prop the last prop wont be added to the className. why ?
ex.
${(props) => (props.dark ? `bg-theme-bgdark` : `bg-theme-bg`)}
${(props) => (props.color ? `${props.color}` : `text-theme-text`)}
${(props) => (props.border? `${props.border}` : ``)} //this wont execute
The props don't seems to be correctly propagated to the React Element.
<Input onChange={console.log} onFocus={() => console.log(`focus`)} />
const Input = tw.input``
Check the example directory for a reproducible example
I'm getting the following TypeScript error when I use this package in a .tsx file.
TS2349: This expression is not callable. Not all constituents of type 'FunctionTemplate | undefined' are callable. Type 'undefined' has no call signatures.
4.0.5
1.0.6
TypeScript configuration:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"./node_modules",
"**/**/*.svg"
]
}
Hi, first of all: Amazing Project! Thank you for building this!
So, when I run npm start
the console spits out: can't find src/ folder but still serves the react app correctly o.0
WARNING in ./node_modules/tailwind-styled-components/dist/tailwind.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/Users/worker/development/hundertschaft-com/node_modules/tailwind-styled-components/src/tailwind.tsx' file: Error: ENOENT: no such file or directory, open '/Users/worker/development/hundertschaft-com/node_modules/tailwind-styled-components/src/tailwind.tsx'
@ ./node_modules/tailwind-styled-components/dist/index.js 14:35-56
@ ./src/App.tsx 7:0-44 9:19-24
@ ./src/index.tsx 7:0-24 11:33-36
3 warnings have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
webpack 5.68.0 compiled with 3 warnings in 3036 ms
No issues found.
Not sure if simply publishing the src
folder to npm would fix this.
Steps
npm i -D tailwind-styled-components
Thanks!
Hi there! ๐๐ป
Considerate the following simple scenario:
// H1.js
import tw from "tailwind-styled-components";
export const H1 = tw.h1`
text-3xl
text-blue-700
font-bold
`;
// Home.js
...
<H1 className="mt-4 pb-6">Hallo!</H1>
...
To me the final className
attribute would be "text-3xl text-blue-700 font-bold mt-4 pb-6". But instead, the outer most className
attribute is being placed at the beginning of the className yielding to "mt-4 pb-6 text-3xl text-blue-700 font-bold". But, IMHO, in the described scenario the parameter passed to the component should be concatenated at the end of the className
attribute allowing, among other things, overwrite the classes defined at the component code.
I checked the code and it looks like that it concatenates the template
classes with the inheritedClasses
. But I think that the "newClasses" in this scenario would be the ones being received as parameter by the use of the component.
What do you think? I'm available to create the PR if this makes sense.
Running into some type issues but a basic button that has props passed through
I'm using the default next.js typescript configuration
{
"compilerOptions": {
"baseUrl": "src",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
Hello,
Awesome work Mathias.
Is it possible to implement 3rd party plugins like tailwind-rtl to it?
Cheers
Hello again. Thanks for the 2.1.2 version fix.
Unfortunately, upgrading to 2.1.4 and running tsc
presented an error on a whole different level:
<--- Last few GCs --->
[2053:0x5bd9060] 88488 ms: Scavenge 2027.0 (2073.3) -> 2023.9 (2074.5) MB, 19.1 / 0.0 ms (average mu = 0.355, current mu = 0.179) allocation failure
[2053:0x5bd9060] 88515 ms: Scavenge 2028.2 (2074.5) -> 2025.9 (2077.8) MB, 11.2 / 0.0 ms (average mu = 0.355, current mu = 0.179) allocation failure
[2053:0x5bd9060] 88542 ms: Scavenge 2031.4 (2077.8) -> 2028.8 (2096.0) MB, 10.2 / 0.0 ms (average mu = 0.355, current mu = 0.179) allocation failure
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0xb00e10 node::Abort() [/usr/local/bin/node]
2: 0xa1823b node::FatalError(char const*, char const*) [/usr/local/bin/node]
3: 0xcee09e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
4: 0xcee417 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
5: 0xea65d5 [/usr/local/bin/node]
6: 0xeb5cad v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
7: 0xeb89ae v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
8: 0xe79b12 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/usr/local/bin/node]
9: 0xe74[43](https://github.com/foroscom/foros-fe/runs/5145598143?check_suite_focus=true#step:5:43)c v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawArray(int, v8::internal::AllocationType) [/usr/local/bin/node]
10: 0xe7[45](https://github.com/foroscom/foros-fe/runs/5145598143?check_suite_focus=true#step:5:45)15 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithFiller(v8::internal::Handle<v8::internal::Map>, int, v8::internal::Handle<v8::internal::Oddball>, v8::internal::AllocationType) [/usr/local/bin/node]
11: 0x10dd41e v8::internal::MaybeHandle<v8::internal::OrderedHashMap> v8::internal::OrderedHashTable<v8::internal::OrderedHashMap, 2>::Allocate<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType) [/usr/local/bin/node]
12: 0x10dd4d3 v8::internal::MaybeHandle<v8::internal::OrderedHashMap> v8::internal::OrderedHashTable<v8::internal::OrderedHashMap, 2>::Rehash<v8::internal::Isolate>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::OrderedHashMap>, int) [/usr/local/bin/node]
13: 0x11e9805 v8::internal::Runtime_MapGrow(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]
14: 0x15e7cf9 [/usr/local/bin/node]
Aborted (core dumped)
error Command failed with exit code 134.
Not really sure where to begin debugging, since no other output is present. The JS itself works as expected, but tsc
runs forever and then OOMs.
Do you have any idea what might have caused it?
I mean, in a very large project. I'm looking for great tools to help me out, and I'm kinda interested in this one. Can anyone, who put this in production before, tell me if it had a nice performance?
Hi devs
how we can write nested css like below:
tw.div`
flex
& h2 {
text-red-500
}
`
thank you for this awesome work Mathias
while building a UI library with this I've run into a number of scenarios where I've wanted to have the attrs functionality that styled has. My use case doesn't require the complexity (or even dynamic capabilities) that styled has, I mainly just want be able to attach attributes to the element like, type
, role
, aria-*
, etc.
Failed example:
โ npm i -D [email protected]
npm ERR! Cannot read property 'version' of undefined
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/riywo/.npm/_logs/2021-05-06T09_19_38_961Z-debug.log
No issue with 1.0.7
:
โ npm i -D [email protected]
added 20 packages, and audited 764 packages in 3s
130 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Probably due to this unnecessary circular dependency:
Tailwind-Styled-Component/package.json
Line 52 in 4f7a746
This probably works up to 1.x
because ^1.0.5
accepts minor/patch versions: https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept
However, it is hard to reproduce on local machine. Could you try to release a new version without this dependency?
My environment:
Darwin 20.4.0
node v14.15.1
npm v7.5.2
Have a such global style:
import {createGlobalStyle} from "styled-components"
/** Body setup */
export const GlobalStyle = createGlobalStyle`
body {}
`
Need to override it on:
<body class="min-h-screen bg-gray-100 text-sm" >
Love the idea of this package, is there any way to get the vscode intellisense feature to work along with this?
From what i see is all the elements are hard-coded , I am not sure if that is by design or limited it would have been better to rather add support for custom element and generalize it, instead of having this attached to react only supported element
so right now
Package.json
"next": "^10.1.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"styled-components": "^5.2.2",
"swr": "^0.5.5"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"babel-plugin-styled-components": "^1.12.0",
"concurrently": "^6.0.0",
"eslint": "^7.23.0",
"eslint-plugin-react": "^7.23.1",
"husky": "^4.3.8",
"lint-staged": "^10.5.4",
"prettier": "^2.2.1",
"tailwind-styled-components": "^1.0.7",
Hero.js
import styled from 'styled-components';
import tw from 'tailwind-styled-components';
const Section = tw.section`
bg-indigo-600
`;
export function Splash() {
return (
<Section>
<h1>HERO</h1>
</Section>
);
}
Browser view
<section class="bg-indigo-600">
<h1>HERO</h1>
</section>
Browser console
//....nothing. There is no indication that the styles have been added other than the browser view which you see above.
Trying to figure out how to get the code behind those classnames to get loaded so the browser is rending the classname correctly.
issue when use the library
when I use
import tw from 'tailwind-styled-components';
import InfiniteScroll from 'react-infinite-scroll-component';
const StyledInfiniteScroll = tw(InfiniteScroll)`
list
scroll-custom
rounded-md
bg-custom-gray-2
absolute
top-11
w-full
shadow-lg
max-h-30
overflow-y-auto
`;
the vscode take much time to organize imports
Saving '******.tsx': Applying code action 'Organize Imports'. take 3-5 mins
but when save success and the app recompile its UI its show successfully
if I use
> Typescript: Restart TS server
import tw from 'tailwind-styled-components';
import InfiniteScroll from 'react-infinite-scroll-component';
const StyledInfiniteScroll = tw.div`
list
scroll-custom
rounded-md
bg-custom-gray-2
absolute
top-11
w-full
shadow-lg
max-h-30
overflow-y-auto
`;
<StyledInfiniteScroll>
<InfiniteScroll>
</InfiniteScroll>
</StyledInfiniteScroll>
all work fine
import Image from 'next/image'
<Image className="absolute inset-0 h-full w-full rounded-lg bg-gray-400 object-cover shadow-md" etc />
How do I tsc this> Thanks.
Tried moving into the enclosing div but not at all the same thing . am reading that Next changed the way Image behaves in the latest version that has broken a lot of people's code. One suggestion is to move the css into the enclosing div but has to be "relative". Tried this but image looks distorted.
I know tailwind css detects whether a class is used based on className
. Since components defined using this format are not using className
, will the resulting css file still include the correct class names?
If I use a tailwind framework, like daisy ui, will this still work?
Cannot export a component
export const MyContainer = tw.div`flex`
Getting this error:
Exported variable 'Container' has or is using name 'TailwindComponent' from external module ".../node_modules/tailwind-styled-components/dist/tailwind" but cannot be named.ts(4023)
I get the following error only when I try to use tailwind styled components:
WARNING in ./node_modules/tailwind-styled-components/dist/domElements.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/domElements.ts' file: Error: ENOENT: no such file or directory, open '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/domElements.ts'
@ ./node_modules/tailwind-styled-components/dist/tailwind.js 15:38-62
@ ./node_modules/tailwind-styled-components/dist/index.js 14:35-56
@ ./src/App.js 6:0-44 21:16-22
@ ./src/index.js 7:0-24 11:33-36
WARNING in ./node_modules/tailwind-styled-components/dist/index.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/index.ts' file: Error: ENOENT: no such file or directory, open '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/index.ts'
@ ./src/App.js 6:0-44 21:16-22
@ ./src/index.js 7:0-24 11:33-36
WARNING in ./node_modules/tailwind-styled-components/dist/tailwind.js
Module Warning (from ./node_modules/source-map-loader/dist/cjs.js):
Failed to parse source map from '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/tailwind.tsx' file: Error: ENOENT: no such file or directory, open '/home/amejia/code/projects/cryptopunks-clone/node_modules/tailwind-styled-components/src/tailwind.tsx'
@ ./node_modules/tailwind-styled-components/dist/index.js 14:35-56
@ ./src/App.js 6:0-44 21:16-22
@ ./src/index.js 7:0-24 11:33-36
3 warnings have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.
webpack 5.65.0 compiled with 3 warnings in 1682 ms
I created my project following Tailwind CSS v3 documentation and Tailwind works fine in classNames, but whenever I try to use React Styled Components, although the styles are applied, the previous error pops up.
Hello. We have upgraded the package from 2.0.4 to 2.1.1 and received new typescript errors all over the codebase. Most of them indicate some kind of issue with the new $as
prop. For example:
src/components/Navigation/NavBar.tsx(225,12): error TS2769: No overload matches this call.
Overload 1 of 2, '(props: { onClick?: MouseEventHandler<HTMLAnchorElement> | undefined; className?: string | undefined; color?: string | undefined; id?: string | undefined; ... 262 more ...; $active?: boolean | undefined; } & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Property '$as' is missing in type '{ children: TFunctionResult; onClick: () => void; }' but required in type '{ onClick?: MouseEventHandler<HTMLAnchorElement> | undefined; className?: string | undefined; color?: string | undefined; id?: string | undefined; ... 262 more ...; $active?: boolean | undefined; }'.
Overload 2 of 2, '(props: StyledComponentPropsWithAs<TailwindComponent<Pick<Pick<ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement>, "key" | keyof AnchorHTMLAttributes<...>> & RefAttributes<...>, "key" | keyof AnchorHTMLAttributes<...>> & RefAttributes<...>>, ... 4 more ..., TailwindComponent<...>>): ReactElement<...>', gave the following error.
Property '$as' is missing in type '{ children: TFunctionResult; onClick: () => void; }' but required in type '{ onClick?: MouseEventHandler<HTMLAnchorElement> | undefined; className?: string | undefined; color?: string | undefined; id?: string | undefined; ... 262 more ...; $active?: boolean | undefined; }'.
The source code is as simple as follows:
const LogInAnchor = tw.a`
...
`
const TwAnchor = tw(LogInAnchor)`
...
`
const Anchor = styled(TwAnchor)<{ $active?: boolean }>`
...
`
// later, error at the render site
<Anchor>Logout</Anchor>
By looking at the library's source code I couldn't understand why is the $as
prop reported as missing, since it seems to be optional. Do you have any idea why this error occurs and how to fix it?
Hi,
when I try to do this:
const Heading = tw.h1<HeadingProps>`
text-2xl
${(props) => props.primary && 'text-red-500'}
`;
where primary
is of type boolean | undefined
...
I get a TypeError:
Type 'false | "text-red-500" | undefined' is not assignable to type 'string | null | undefined'.
Type 'boolean' is not assignable to type 'string'.ts(2322)
[tailwind.d.ts(23, 83): ]()The expected type comes from the return type of this signature.
Given that there is this code already, could the allowed return type for template components be extended to include false
? (Or perhaps even more "falsy" typescript types?)
Edit:
The reason for this request is that the only other way I see to achieve this is to use props.primary ? 'text-red-500' : undefined
, which I find overly verbose for this task
input:
const Div1 = tw.span`text-red-500`
const Div2 = tw.div`bg-green-500`
const Div3 = tw(Div1)`rounded-full`
const Div4 = tw(Div2)`select-all`
export default () => {
return <Div3 $as={Div4}>foo</Div3>
}
output:
<div class="bg-green-500 select-all rounded-full">foo</div>
loss the Div1's className
ERROR in .../node_modules/tailwind-styled-components/dist/tailwind.d.ts
[tsl] ERROR in .../node_modules/tailwind-styled-components/dist/tailwind.d.ts(2,38)
TS1005: '>' expected.
ERROR in .../node_modules/tailwind-styled-components/dist/tailwind.d.ts
[tsl] ERROR in .../node_modules/tailwind-styled-components/dist/tailwind.d.ts(2,56)
TS1109: Expression expected.
โน ๏ฝขwdm๏ฝฃ: Failed to compile.
my code:
import tw from 'tailwind-styled-components'
const Root = tw.div` flex `;
file in which the error occures (i haven't modified anything):
import React from "react";
declare type TransientProps = Record<`$${string}`, any>;
export declare type FunctionTemplate<P, E> = <K extends TransientProps = {}>(template: TemplateStringsArray, ...templateElements: ((props: P & K) => string | undefined | null)[]) => React.ForwardRefExoticComponent<React.PropsWithoutRef<P & K> & React.RefAttributes<E>>;
interface ClassNameProp {
className?: string;
}
declare function functionTemplate<P extends ClassNameProp, E = any>(Element: React.ComponentType<P>): FunctionTemplate<P, E>;
export declare type IntrinsicElements = {
[key in keyof JSX.IntrinsicElements]: FunctionTemplate<JSX.IntrinsicElements[key], any>;
};
declare const tw: typeof functionTemplate & IntrinsicElements;
export default tw;
Hi! First of all, this is a great library as it makes working with Tailwind a lot easier, and I'm very thankful for that.
Like the documentation explains, this library doesn't override parent classes, it just concatenates the different classes and the result will depend on each case. Which brings to the following suggestion: how possible would it be to switch the use of the current library tailwindcss-classnames
to tailwind-merge
(https://github.com/dcastil/tailwind-merge) as this other library already handles tailwind classes overriding?
I understand that this might be a breaking change given the current state of the library (if it's a hard change, but maybe it could be configurable?). However I believe users would benefit a lot more if it were possible to override parent classes.
Thanks!
I would like to do something like this
const className = tw.cls`
flex
items-center
`
className === 'flex items-center'
Also, it could be usefull when props change many classes
const Title = tw.h1<TitleProps>`
${(p) => (p.$large ? tw.cls`
flex
items-center
h-10
px-4
` : "text-base")}
text-indigo-500
`
How do you select child elements ? This does not work:
const Container = tw.div`
grid
grid-cols-2
bg-green-300
.container-child {
//....container child style
}
`;
Hello,
is there a way to use TypeScript generics in Tailwind component declaration?
Something like this:
interface IButton {
xl?: boolean;
}
const TwButton = tw.button<IButton>`
text-blue-400
text-lg
cursor-pointer
py-2
px-4
rounded
justify-center
items-center
font-bold
ease-linear
select-none
focus:outline-none
${p => p.xl && "py-4 px-10 text-xl"}
`;
Thanks
I tried to recreate the example from the readme where RedContainer should override the background color of DefaultContainer.
Instead of bg-blue-600
getting replaced with bg-red-300
, I get both classes in the result:
<div class="bg-red-300 flex items-center bg-blue-600">
<!-- children -->
</div>
Is there anything I am missing?
I am using version 2.0.2.
Thanks!
Typo on README Example:
// Create a react component that renders a
SHOULD BE
const SpecialBlueContainer = styled.section
Given the following code
const TimelineCurrent = tw.div<{ position: number }>`
absolute
left-0
top-[0.575rem]
${(p) => `w-[calc(${p.position}%-0.75rem)]`}
h-[0.35rem]
`;
it renders the following HTML
<div position="100" class="absolute left-0 top-[0.575rem] w-[calc(100%-0.75rem)] h-[0.35rem]"></div>
But the w-[calc(100%-0.75rem)]
part is not picked up by Tailwind JIT, so it has no effect. Am I doing something wrong here?
It seems like props are passed as an attribute and when I pass boolean, It throws error on the console. I am using next.js with typescript.
This is the error
Warning: Received `true` for a non-boolean attribute `block`.
If you want to write it to the DOM, pass a string instead: block="true" or block={value.toString()}.
button
functionTemplate/</<@webpack-internal:///./node_modules/tailwind-styled-components/dist/tailwind.js:34:101
Component looks like this
import tw from 'tailwind-styled-components';
interface Props {
layout?: 'primary' | 'outline';
disabled?: boolean;
block?: boolean;
size?: 'small' | 'medium' | 'large';
}
const Button = tw.button`
flex justify-center items-center border border-solid font-medium rounded-sm transition-all duration-300 ease-in-out
${(props: Props) =>
props.layout === 'primary' &&
'border-primary-400 bg-primary-400 text-white hover:bg-primary-500 hover:border-primary-600'}
${(props: Props) =>
props.layout === 'outline' &&
'border-gray-300 text-gray-700 hover:border-blue-500 hover:text-blue-500'}
${(props: Props) =>
props.disabled && 'bg-gray-50 border-gray-200 text-gray-200'}
${(props: Props) => props.size === 'small' && 'px-2 py-2 text-xs'}
${(props: Props) => props.size === 'medium' && 'px-4 py-3 text-xs'}
${(props: Props) => props.size === 'large' && 'px-5 py-4 text-lg'}
${(props: Props) => props.block && 'w-full'}
`;
export default Button;
The workaround is using number as boolean block ? 1 : 0
This is probably a silly question, but I can't understand how to use breakpoint prefixes with this library.
How would you translate this piece of code?
<div class="w-16 md:w-32 lg:w-48">
I've tried so many things, but none works. My first approach was something like this:
const MyDiv = tw.div`
w-16
md: w-32
lg: w-48
`;
But didn't work :(
$as prop appears to break className merging inheritance
Simple example
// base tw styled component
export const Heading = tw.p`
text-4xl font-bold text-gray-700
`
// extend the base Heading styled component
export const Display = tw(Heading)`
text-6xl
`
const WithoutAs = ({children}) => {
return (
// without the $as prop, all classnames will be merged in correctly.
// text-6xl font-bold text-gray-700 border-2 p-4
<Display className="border-2 p-4">{children}</Display>
)
}
const WithAs = ({children}) => {
return (
// with the $as prop, only the most recent component's classes will be used
// text-6xl border-2 p-4
<Display className="border-2 p-4" $as="h1">{children}</Display>
)
}
How can I define (dynamic) pseudo-elements (:before
or :after
)?
I know this is not natively possible in Tailwind yet, but I was wondering if there is a way to work around this.
I am trying to achieve the following:
.element:before {
color: $color;
}
where $color
should be a dynamic variable.
I wonder if it's possible to pass props as they are to a styled component that was extended?
For instance:
import React from "react"
import styled from "styled-components"
import tw from "tailwind-styled-components"
interface TitleProps {
$large: boolean;
}
const StyledTitle = styled.h1<TitleProps>`
font-size: ${(p) => (p.$large ? '1337px' : '42px' )}
`
const Title = tw(StyledTitle)`
text-red-800
`
render <Title $large={true}>Hello World</Title>
What I noticed is that $large
is not accessible on StyledTitle
. It's only accessible on Title
.
Is there a way to ensure I can use the TitleProps
on StyledTitle
?
Example usage:
const Button = tw.button`inline-flex items-center p-2`
<Button as="a" href="#">Link</Button>
// renders as
<a href="#" class="inline-flex items-center p-2">Link</a>
Hi ๐๐ผ
First of all thanks for this great project ๐๐ผ
I am in the process of replacing "normal" styled components with Tailwind-Styled-Components in a semi large code base.
During this I have hit a few questions I hope you might have some suggestions for ๐
For styled components we are used to formatting the contents of the template using Prettier, any suggestions for automatic formatting of the tw blocks (Mainly using vs code)
Linting the tailwind classes to make sure only existing classes are used, do you know of any solution for this?
Code hints from Tailwind extension inside the templated code strings.
As seen on the image, the colors are shown in the main portion, but not in the returns.
Thought this where the place to use tw`text-danger-700` but that seems to not be correct.
Hope it is okay to post these questions here, and that someone have some nice suggestions ๐
@MathiasGilson great lib!
One thing I think is missing is adding displayName like styled components does i.e. if its tw.label
the displayName would be tw.label
instead of Anonymous.
I can possibly create a pull request later this week!
Hello, it would be nice to have this in your library, or is it already there?
Example of using arbitrary variants to style elements with a custom selector:
import tw from 'tailwind-styled-components'
const Button = tw.button`
bg-black
[> i]:block
[> span]:(text-blue-500 w-10)
[div.container]:(grid m-8)
`
const Component = () => (
<Button>
<i>Icon</i>
<span>Label</span>
<div className="container">Container</div>
</Button>
)
On styled-components' original docs, there's a way that we can pass a function to the styled component's template literal and adapt the primary state based on its props:
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
`;
Since tailwind CSS doesn't support interpolations, i.e. bg-{color}
, the exact code above can't work for tailwind-styled-components. But perhaps we can have this functionality here as well. I thought the following syntax should work:
const Button = tw.button`
bg: ${props => props.primary ? "red-500" : "white"};`;
text: ${props => props.primary ? "white" : "red-500"};`;
And then identify the properties mentioned, so it becomes something like
{props.primary ? 'bg-red-500 text-white' : 'bg-white text-red-500'}
Is there a way it could be done?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.