import plugin from 'tailwindcss/plugin'; import { fontFamily } from 'tailwindcss/defaultTheme'; import type { Config } from 'tailwindcss'; import { BrainfishColors } from './src/colors'; const { blue, dark, green, lime, magenta, orange, pink, primary, purple, red, teal, yellow } = BrainfishColors; const preset: Partial = { darkMode: ['class'], theme: { container: { center: true, padding: '2rem', screens: { '2xl': '1400px', }, }, extend: { fontFamily: { ...fontFamily, sans: ['var(--bfc-font-family)', 'system-ui', 'sans-serif'], fraunces: ['var(--font-fraunces)', 'serif'], inter: ['var(--font-inter)', 'sans-serif'], }, fontWeight: { bold: '700', normal: '400', }, colors: { transparent: 'transparent', primary: 'var(--bfc-primary)', success: { DEFAULT: 'var(--bfc-success-bg)', foreground: 'var(--bfc-success-text)', }, destructive: { DEFAULT: 'var(--bfc-destructive-bg)', foreground: 'var(--bfc-destructive-text)', }, warning: 'var(--bfc-warning-bg)', base: { orange: orange.DEFAULT, yellow: yellow.DEFAULT, primary: primary.DEFAULT, green: green.DEFAULT, blue: blue.DEFAULT, purple: purple.DEFAULT, pink: pink.DEFAULT, red: red.DEFAULT, lime: lime.DEFAULT, teal: teal.DEFAULT, magenta: magenta.DEFAULT, }, dark, orange, yellow, green, blue, purple, pink, red, border: 'var(--bfc-border)', input: 'var(--bfc-input)', ring: 'var(--bfc-border)', background: 'var(--bfc-background)', foreground: 'var(--bfc-foreground)', feedback: { positive: 'var(--bfc-feedback-positive)', negative: 'var(--bfc-feedback-negative)', }, link: 'var(--bfc-link)', surface: { DEFAULT: 'var(--bfc-surface)', border: 'var(--bfc-surface-border)', }, secondary: { DEFAULT: 'var(--bfc-secondary)', foreground: 'var(--bfc-secondary-foreground)', }, muted: { DEFAULT: 'var(--bfc-muted)', foreground: 'var(--bfc-muted-foreground)', }, accent: { DEFAULT: 'var(--bfc-accent)', foreground: 'var(--bfc-accent-foreground)', }, popover: { DEFAULT: 'var(--bfc-popover)', foreground: 'var(--bfc-foreground)', }, card: { DEFAULT: 'var(--bfc-card)', foreground: 'var(--bfc-card-foreground)', }, }, textColor: { primary: 'var(--bfc-primary-foreground)', 'primary-foreground': 'var(--bfc-primary-foreground)', default: 'var(--bfc-text-default)', subtle: 'var(--bfc-text-subtle)', subtlest: 'var(--bfc-text-subtlest)', success: 'var(--bfc-success-text)', destructive: 'var(--bfc-destructive-text)', warning: 'var(--bfc-warning-text)', }, backgroundColor: { success: 'var(--bfc-success-bg)', destructive: 'var(--bfc-destructive-bg)', warning: 'var(--bfc-warning-bg)', surface: 'var(--bfc-white)', }, borderColor: { success: 'var(--bfc-success-border)', destructive: 'var(--bfc-destructive-border)', warning: 'var(--bfc-warning-border)', }, 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', }, maxWidth: { threadWidth: '1400px', }, spacing: { headerHeight: '64px', md: '16px', lg: '24px', xl: '32px', }, gridTemplateColumns: { 12: 'repeat(12, minmax(0, 1fr))', }, }, }, plugins: [ require('tailwindcss-animate'), require('@tailwindcss/container-queries'), plugin(function ({ addBase }) { addBase({ 'ul': { listStyleType: 'disc' }, 'ol': { listStyleType: 'decimal' }, }); }), plugin(function ({ addUtilities }) { addUtilities({ // Typography - Headings ...Object.entries({ 'xxl': { fontSize: '2rem', lineHeight: '2.25rem', fontFamily: 'var(--bfc-heading-xxl-font-family)' }, 'xl': { fontSize: '1.75rem', lineHeight: '2rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'lg': { fontSize: '1.5rem', lineHeight: '1.75rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'm': { fontSize: '1.25rem', lineHeight: '1.5rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'sm': { fontSize: '1rem', lineHeight: '1.25rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'xs': { fontSize: '0.875rem', lineHeight: '1.25rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'xxs': { fontSize: '0.75rem', lineHeight: '1rem', fontFamily: 'var(--bfc-v2-font-family)' }, 'xxxs': { fontSize: '0.625rem', lineHeight: '0.875rem', fontFamily: 'var(--bfc-v2-font-family)' }, }).reduce( (acc, [size, styles]) => { acc[`.heading-${size}`] = { 'font-family': styles.fontFamily, 'font-size': styles.fontSize, 'font-style': 'normal', 'font-weight': '700', 'line-height': styles.lineHeight, }; return acc; }, {} as Record, ), // Typography - Paragraph ...Object.entries({ 'lg': { fontSize: '1rem', lineHeight: '1.5rem' }, 'md': { fontSize: '0.875rem', lineHeight: '1.25rem' }, 'sm': { fontSize: '0.75rem', lineHeight: '1rem' }, }).reduce( (acc, [size, styles]) => { acc[`.paragraph-${size}`] = { 'font-family': 'var(--bfc-v2-font-family)', 'font-size': styles.fontSize, 'font-style': 'normal', 'font-weight': '400', 'line-height': styles.lineHeight, }; return acc; }, {} as Record, ), }); }), plugin(function ({ addUtilities }) { const dashedBorderUtilities: Record = {}; const gradient = (deg: number, color: string) => `repeating-linear-gradient(${deg}deg, ${color}, ${color} 8px, transparent 8px, transparent 16px)`; const createBorderUtility = (colorValue: string, sides: number[], baseName: string) => { const gradients = [0, 90, 180, 270].map((deg) => { const color = sides.includes(deg) ? colorValue : 'transparent'; return gradient(deg, color); }); const className = baseName ? `.custom-dashed-border-${baseName}` : '.custom-dashed-border'; return { [className]: { position: 'relative', border: 'none', }, [`${className}::before`]: { content: '""', position: 'absolute', inset: '0', 'background-image': gradients.join(','), 'background-position': '0 0, 0 0, 100% 0, 0 100%', 'background-size': '1px 100%, 100% 1px, 1px 100%, 100% 1px', 'background-repeat': 'no-repeat', 'pointer-events': 'none', 'border-radius': 'inherit', 'z-index': '0', }, }; }; const generateUtilitiesForColor = (colorValue: string, baseName: string) => { const utilities: Record = {}; Object.assign(utilities, createBorderUtility(colorValue, [0, 90, 180, 270], baseName)); Object.assign(utilities, createBorderUtility(colorValue, [90], baseName ? `t-${baseName}` : 't')); Object.assign(utilities, createBorderUtility(colorValue, [180], baseName ? `r-${baseName}` : 'r')); Object.assign(utilities, createBorderUtility(colorValue, [270], baseName ? `b-${baseName}` : 'b')); Object.assign(utilities, createBorderUtility(colorValue, [0], baseName ? `l-${baseName}` : 'l')); Object.assign(utilities, createBorderUtility(colorValue, [0, 180], baseName ? `x-${baseName}` : 'x')); Object.assign(utilities, createBorderUtility(colorValue, [90, 270], baseName ? `y-${baseName}` : 'y')); return utilities; }; Object.assign(dashedBorderUtilities, generateUtilitiesForColor('var(--bfc-border)', '')); Object.entries(BrainfishColors).forEach(([colorName, colorShades]) => { Object.entries(colorShades).forEach(([shade, colorValue]) => { const baseName = shade === 'DEFAULT' ? colorName : `${colorName}-${shade}`; Object.assign(dashedBorderUtilities, generateUtilitiesForColor(colorValue as string, baseName)); }); }); addUtilities(dashedBorderUtilities); addUtilities({ '.custom-dashed-border-hover': { '&::before': { 'background-image': 'none', 'border': '1px solid var(--bfc-border)', }, 'box-shadow': '4px 4px 0 0 var(--bfc-border)', }, }); }), ], }; export default preset;