shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
70.73k stars 4.25k forks source link

[feat]: Provide tailwind presets for monorepos #3794

Closed BarakChamo closed 3 months ago

BarakChamo commented 4 months ago

Feature description

I recently had to integrate shadcn/ui in a monorepo and the default setup of tailwind doesn't quite work.

Happily, it was actually very quick to make small changes in order to make the component collection work as a package in a monorepo. I think this would be a welcome addition that is very easy to implement and would make building reusable component packages based on this project much simpler.

I'm opening this as a feature request and not a PR as I'm not familiar with how the CLI generates the template files and I'm sure there are subtleties I'm ignoring in my own implementation.

Changes to autogenerated files

split tailwind.config.ts to config + preset

The new config file: (resetting the content to avoid TS errors, don't think it's required)

import type { Config } from 'tailwindcss'
import preset from './tailwind.preset'

const config: Config = {
    content: preset.content,
    presets: [preset],
}

export default config

The co-located preset file: (note the fixed paths, TW doesn't resolve relative paths in presets)

import type { Config } from 'tailwindcss'

const contentPath = `${__dirname}/src/**/*.{ts,tsx}`

const preset: Config = {
    // darkMode: ['variant'],
    content: [contentPath],
    prefix: '',
    theme: {
        container: {
            center: true,
            padding: '2rem',
            screens: {
                '2xl': '1400px',
            },
        },
        extend: {
            colors: {
                border: 'hsl(var(--border))',
                input: 'hsl(var(--input))',
                ring: 'hsl(var(--ring))',
                background: 'hsl(var(--background))',
                foreground: 'hsl(var(--foreground))',
                primary: {
                    DEFAULT: 'hsl(var(--primary))',
                    foreground: 'hsl(var(--primary-foreground))',
                },
                secondary: {
                    DEFAULT: 'hsl(var(--secondary))',
                    foreground: 'hsl(var(--secondary-foreground))',
                },
                destructive: {
                    DEFAULT: 'hsl(var(--destructive))',
                    foreground: 'hsl(var(--destructive-foreground))',
                },
                muted: {
                    DEFAULT: 'hsl(var(--muted))',
                    foreground: 'hsl(var(--muted-foreground))',
                },
                accent: {
                    DEFAULT: 'hsl(var(--accent))',
                    foreground: 'hsl(var(--accent-foreground))',
                },
                popover: {
                    DEFAULT: 'hsl(var(--popover))',
                    foreground: 'hsl(var(--popover-foreground))',
                },
                card: {
                    DEFAULT: 'hsl(var(--card))',
                    foreground: 'hsl(var(--card-foreground))',
                },
            },
            borderRadius: {
                lg: 'var(--radius)',
                md: 'calc(var(--radius) - 2px)',
                sm: 'calc(var(--radius) - 4px)',
            },
            keyframes: {
                'accordion-down': {
                    from: { height: '0' },
                    to: { height: 'var(--radix-accordion-content-height)' },
                },
                'accordion-up': {
                    from: { height: 'var(--radix-accordion-content-height)' },
                    to: { height: '0' },
                },
            },
            animation: {
                'accordion-down': 'accordion-down 0.2s ease-out',
                'accordion-up': 'accordion-up 0.2s ease-out',
            },
        },
    },
    plugins: [require('tailwindcss-animate')],
}

export default preset

Use in a project

import type { Config } from 'tailwindcss'
import preset from '@this/ui/tailwind-preset'

const config: Config = {
        // this is required, content does carry over from presets automatically
    content: [...(preset.content as string[]), './src/**/*.{js,ts,jsx,tsx}'],
    presets: [preset],
}

In a next.js layout.tsx:

import '@/styles/globals.css' // current project's styles
import '@this/ui/styles.css' // contains only the generated globals.css

Affected component/components

No response

Additional Context

No response

Before submitting

shadcn commented 3 months ago

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.