CSS". Let's hope v2 is not named "Nightmare" ! Goals - Have consistent UI on the website - Make it easier to build new pages - Implement Product Hunt v6 design - Fully type safe What - Foundational utilities - Core UI components
CSS". Let's hope v2 is not named "Nightmare" ! Goals - Have consistent UI on the website - Make it easier to build new pages - Implement Product Hunt v6 design - Fully type safe What - Foundational utilities - Core UI components !
for many components to build their class names. This results in loops and variable generation, resulting in many GCs and slowing rendering. Especially the initial rendering.
for many components to build their class names. This results in loops and variable generation, resulting in many GCs and slowing rendering. Especially the initial rendering.
very complicated core components - core components accepted a lot of props - still needed custom css for borders/shadows - a lot of nesting of core components like Text / Flex ! The bad
// - All properties can be found here - https://tailwindcss.com/docs/utility-first // - PurgeCSS text searches the app, so if a value is in this list it is included in bundle, however interpolation makes sure we don't include all colors type ITailwindClassNames = | 'antialiased' | 'border' | 'cursor-pointer' | `m${IDirection}-${IDistanceWithAuto}` | `w-${IDistanceWithFull}` // ... list all classNames used in the system type IColors = 'brand' | 'gray-50' | 'gray-400' | 'gray-900' | 'white'; type IDirection = 'x' | 'y' | 't' | 'r' | 'b' | 'l'; type IDistance = 0 | 1 | '1.5' | 2 | 4 | 5 | 6 | 8 | 12 | 16 | 40; type IDistanceWithFull = 'full' | IDistance | '3xl'; type IDistanceWithAuto = 'auto' | IDistance; type ISize = 'lg' | 'xl' | '4xl'; type IBreakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; // NOTE(rstankov): Check if strings contains only Tailwind classes // Explanation how this works: // - https://www.kirillvasiltsov.com/writing/type-check-tailwind-css/ export type ITailwind<S> = S extends `${infer Class} ${infer Rest}` ? Class extends ITailwindClassNames ? `${Class} ${ITailwind<Rest>}` : never : S extends `${infer Class}` ? Class extends ITailwindClassNames ? S : never : never; // NOTE(rstankov): Helper to verify class names listed match available Tailwind class names export default function tw<S>(classes: ITailwind<S>) { return classes; }
const root = j(fileInfo.source); // Find import declarations from 'ph/components/dream' root.find(j.ImportDeclaration, { source: { type: 'Literal', value: 'ph/components/dream', }, }) .forEach(path => { let buttonImportSpecifier = path.value.specifiers.find( specifier => specifier.imported && specifier.imported.name === 'Button' ); // If Button is imported from the package, modify the import statement if (buttonImportSpecifier) { // Remove Button from the original import path.value.specifiers = path.value.specifiers.filter(specifier => specifier.imported.name !== 'Button'); // If after removing Button there are no specifiers left, remove the whole import statement if (path.value.specifiers.length === 0) { j(path).remove(); } // Create a new import declaration for Button const newImportDeclaration = j.importDeclaration( [j.importDefaultSpecifier(j.identifier('Button'))], j.literal('ph/components/dream/Button') ); // Insert the new import declaration after the original one j(path).insertAfter(newImportDeclaration); } }); return root.toSource({quote: 'single'}); };
- negative statement (like DON'T) don't work mostly - start new chat sessions often, LLMs are autoregressive - it will get you to 80% and will get stuck - stop using it when stuck ! Prompting Tips "