tailwind.config.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. const colors = require('tailwindcss/colors')
  3. const formsPlugin = require('@tailwindcss/forms')
  4. const lineClampPlugin = require('@tailwindcss/line-clamp')
  5. const formKitTailwind = require('@formkit/themes/tailwindcss')
  6. const headlessUiTailwind = require('@headlessui/tailwindcss')
  7. const plugin = require('tailwindcss/plugin')
  8. const path = require('path')
  9. const fs = require('fs')
  10. // TODO: Move utility code elsewhere?
  11. function* walkSync(dir) {
  12. const files = fs.readdirSync(dir, { withFileTypes: true })
  13. for (const file of files) {
  14. if (file.isDirectory()) {
  15. yield* walkSync(path.join(dir, file.name))
  16. } else {
  17. yield path.join(dir, file.name)
  18. }
  19. }
  20. }
  21. // Here we need to add classes which are only present in the FormSchema back end, as Tailwind
  22. // can't detect them otherwise.
  23. const safelist = new Set()
  24. for (const filePath of walkSync(`${__dirname}/app/models/form_schema/form/`)) {
  25. const content = fs.readFileSync(filePath).toString()
  26. for (const match of content.matchAll(/class: '([^']+)'/g)) {
  27. for (const klass of match[1].split(/[ ]+/)) {
  28. safelist.add(klass)
  29. }
  30. }
  31. }
  32. // Add the moment we can use one tailwind config for the mobile app, but later we need to check
  33. // how this works with different apps.
  34. module.exports = {
  35. content: [`${path.resolve(__dirname)}/app/frontend/**/*.{js,jsx,ts,tsx,vue}`],
  36. theme: {
  37. fontFamily: {
  38. sans: [
  39. '"Fira Sans"',
  40. '"Helvetica Neue"',
  41. 'Helvetica',
  42. 'Arial',
  43. 'sans-serif',
  44. ],
  45. },
  46. colors: {
  47. transparent: 'transparent',
  48. current: 'currentColor',
  49. black: {
  50. DEFAULT: '#191919',
  51. full: colors.black,
  52. },
  53. white: colors.white,
  54. gray: {
  55. DEFAULT: '#999999',
  56. 100: '#D1D1D1',
  57. 150: '#D8D8D8',
  58. 200: '#656567',
  59. 300: '#4C4C4D',
  60. 400: '#323234',
  61. 500: '#282829',
  62. 600: '#262627',
  63. highlight: '#99999926',
  64. light: '#25262D99',
  65. },
  66. blue: {
  67. DEFAULT: '#23A2CD',
  68. dark: '#045972',
  69. highlight: '#23A2CD4D',
  70. },
  71. yellow: {
  72. DEFAULT: '#FFCE33',
  73. highlight: '#FFCE331A',
  74. },
  75. red: {
  76. DEFAULT: '#E54011',
  77. highlight: '#E540111A',
  78. },
  79. green: {
  80. DEFAULT: '#36AF6A',
  81. highlight: '#38AD691A',
  82. },
  83. pink: '#EA4D84',
  84. 'dark-blue': '#045972',
  85. orange: '#F39804',
  86. },
  87. extend: {},
  88. },
  89. plugins: [
  90. formsPlugin,
  91. lineClampPlugin,
  92. formKitTailwind,
  93. plugin(({ addVariant }) => {
  94. addVariant('formkit-populated', [
  95. '&[data-populated]',
  96. '[data-populated] &',
  97. '[data-populated]&',
  98. ])
  99. addVariant('formkit-required', [
  100. '&[data-required]',
  101. '[data-required] &',
  102. '[data-required]&',
  103. ])
  104. addVariant('formkit-is-checked', [
  105. '&[data-is-checked]',
  106. '[data-is-checked] &',
  107. '[data-is-checked]&',
  108. ])
  109. addVariant('formkit-variant-primary', [
  110. '[data-variant="primary"] &',
  111. '[data-variant="primary"]&',
  112. ])
  113. addVariant('formkit-variant-secondary', [
  114. '[data-variant="secondary"] &',
  115. '[data-variant="secondary"]&',
  116. ])
  117. }),
  118. headlessUiTailwind,
  119. ],
  120. safelist: [...safelist.values()],
  121. }