Three regressions from the SSR rendering-modernization migration, all verified live via agent-browser: - BUG A — New Invoice: choosing a client 500'd from /invoice/new/due-date (ClassCastException: DateTime cannot be cast to java.util.Date). `due-date` and `scheduled-payment-date` called `coerce/from-date` on values already decoded to clj-time DateTimes. Drop the coerce; use the decoded dates. - BUG C — Transaction Edit: any whole-form swap (mode toggle, vendor change, add/remove row) 500'd whenever the txn had >=1 autopay-invoice match (ClassCastException at links-body*: PersistentVector cannot be cast to Named). The autopay link-panel's hidden `action` input was missing `:form ""`, so it serialized alongside the main `action` hidden, producing a duplicate param that Ring collapsed to a vector. Add `:form ""` to match the unpaid/rule panels. - Modal sizes: Vendor/Client/Invoice-Pay modals ballooned to full width because resources/public/output.css was missing their arbitrary Tailwind size classes. Root cause: tailwind.config.js `content` never scanned resources/templates/**/*.html (46 Selmer templates the migration introduced), so a rebuild also dropped template-only classes like md:w-[950px]. Add the templates glob and rebuild; all modal size classes now present, no working modal regressed. Docs: add 2026-06-27 QA findings + resumable fix task list; cross-link from the migration plan. Remaining (per the new plan): Vendor/Client inner step-body overflow, wizard step animations, bulk-edit empty-selection 500, footer EDN leak. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
139 lines
5.2 KiB
JavaScript
139 lines
5.2 KiB
JavaScript
/** @type {import('tailwindcss').Config} */
|
|
|
|
const plugin = require('tailwindcss/plugin');
|
|
module.exports = {
|
|
darkMode: "class",
|
|
content: ["./src/**/*.{cljs,clj,cljc}",
|
|
"./resources/templates/**/*.html",
|
|
"./node_modules/flowbite/**/*.js"],
|
|
theme: {
|
|
extend: {
|
|
"keyframes": {
|
|
shake: {
|
|
'0%': { transform: 'translateX(0px)' },
|
|
'12.5%': { transform: 'translateX(-5px)' },
|
|
'25%': { transform: 'translateX(0px)' },
|
|
'37.5%': { transform: 'translateX(5px)' },
|
|
'50%': { transform: 'translateX(0px)' },
|
|
'62.5%': { transform: 'translateX(-5px)' },
|
|
'75%': { transform: 'translateX(5px)' },
|
|
'87.5%': { transform: 'translateX(5px)' },
|
|
'100%': { transform: 'translateX(0px)' },
|
|
},
|
|
gentleGrow: {
|
|
"0%": {
|
|
"transform": "scale(1.0)",
|
|
"animation-timing-function": "cubic-bezier(0.8, 0, 1, 1)"
|
|
},
|
|
"50%": {
|
|
"transform": "scale(1.1)",
|
|
"animation-timing-function": "cubic-bezier(0, 0, 0.2, 1)"
|
|
},
|
|
"100%": {
|
|
"transform": "scale(1.0)",
|
|
"animation-timing-function": "cubic-bezier(0.8, 0, 1, 1)"
|
|
}
|
|
},
|
|
slideUp: {
|
|
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
|
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
|
|
}
|
|
},
|
|
animation: {
|
|
'shake': 'shake 0.5s ease-out 1',
|
|
"gg": "gentleGrow 1s infinite",
|
|
"slideUp": 'slideUp 0.5s ease-out forwards'
|
|
},
|
|
"fontFamily": {
|
|
"sans": ["Calibri", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"]
|
|
|
|
},
|
|
"colors": {
|
|
"green": {
|
|
"50": "#f2f8ea",
|
|
"100": "#e4f0d5",
|
|
"200": "#c9e1ab",
|
|
"300": "#afd382",
|
|
"400": "#94c458",
|
|
"500": "#79b52e",
|
|
"600": "#619125",
|
|
"700": "#496d1c",
|
|
"800": "#304812",
|
|
"900": "#182409"
|
|
},
|
|
"primary": {
|
|
"50": "#f2f8ea",
|
|
"100": "#e4f0d5",
|
|
"200": "#c9e1ab",
|
|
"300": "#afd382",
|
|
"400": "#94c458",
|
|
"500": "#79b52e",
|
|
"600": "#619125",
|
|
"700": "#496d1c",
|
|
"800": "#304812",
|
|
"900": "#182409"
|
|
},
|
|
"blue": {
|
|
"50": "#e6f5fd",
|
|
"100": "#ccebfb",
|
|
"200": "#99d7f7",
|
|
"300": "#66c4f2",
|
|
"400": "#33b0ee",
|
|
"500": "#009cea",
|
|
"600": "#007dbb",
|
|
"700": "#005e8c",
|
|
"800": "#003e5e",
|
|
"900": "#001f2f"
|
|
},
|
|
"secondary": {
|
|
"50": "#e9f5e8",
|
|
"100": "#d2ebd2",
|
|
"200": "#a6d7a4",
|
|
"300": "#79c377",
|
|
"400": "#4daf49",
|
|
"500": "#209b1c",
|
|
"600": "#1a7c16",
|
|
"700": "#135d11",
|
|
"800": "#0d3e0b",
|
|
"900": "#061f06"
|
|
},
|
|
"red": {
|
|
"50": "#ffe6e6",
|
|
"100": "#ffcdcd",
|
|
"200": "#ff9a9a",
|
|
"300": "#ff6868",
|
|
"400": "#ff3535",
|
|
"500": "#ff0303",
|
|
"600": "#cc0202",
|
|
"700": "#990202",
|
|
"800": "#660101",
|
|
"900": "#330101"
|
|
},
|
|
"orange": {
|
|
"50": "#fef2e8",
|
|
"100": "#fde6d1",
|
|
"200": "#fbcca2",
|
|
"300": "#f8b374",
|
|
"400": "#f69945",
|
|
"500": "#f48017",
|
|
"600": "#c36612",
|
|
"700": "#924d0e",
|
|
"800": "#623309",
|
|
"900": "#311a05"
|
|
}
|
|
|
|
}
|
|
}
|
|
} ,
|
|
plugins: [
|
|
require('flowbite/plugin'),
|
|
plugin(function ({ addVariant }) {
|
|
addVariant('htmx-settling', ['&.htmx-settling', '.htmx-settling &'])
|
|
addVariant('htmx-request', ['&.htmx-request', '.htmx-request &'])
|
|
addVariant('htmx-swapping', ['&.htmx-swapping', '.htmx-swapping &'])
|
|
addVariant('htmx-added', ['&.htmx-added', '.htmx-added &'])
|
|
}),
|
|
]
|
|
}
|