chore(dependencies): update Tailwind CSS and related configurations
- Removed @tailwindcss/postcss from devDependencies and updated tailwindcss to version 3.4.15 for improved styling. - Added autoprefixer as a new dependency to enhance CSS compatibility. - Updated postcss.config.js to reflect the new Tailwind CSS plugin structure. - Created a new tailwind.config.js file to define Tailwind's configuration. - Adjusted CSS imports in index.css to utilize Tailwind's utility classes. - Refined focus styles across various components for better accessibility and visual consistency.
This commit is contained in:
1583
worklenz-frontend/package-lock.json
generated
1583
worklenz-frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,6 @@
|
|||||||
"worklenz": "file:"
|
"worklenz": "file:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.11",
|
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@testing-library/user-event": "^14.6.1",
|
"@testing-library/user-event": "^14.6.1",
|
||||||
@@ -74,10 +73,11 @@
|
|||||||
"@types/react-dom": "19.0.0",
|
"@types/react-dom": "19.0.0",
|
||||||
"@types/react-window": "^1.8.8",
|
"@types/react-window": "^1.8.8",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
"postcss": "^8.5.2",
|
"postcss": "^8.5.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.13",
|
"prettier-plugin-tailwindcss": "^0.6.13",
|
||||||
"rollup": "^4.40.2",
|
"rollup": "^4.40.2",
|
||||||
"tailwindcss": "^4.1.11",
|
"tailwindcss": "^3.4.15",
|
||||||
"terser": "^5.39.0",
|
"terser": "^5.39.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
"vite": "^6.3.5",
|
"vite": "^6.3.5",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
'@tailwindcss/postcss': {},
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
||||||
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
||||||
}
|
}
|
||||||
focus:outline-hidden focus:ring-1 focus:ring-blue-500
|
focus:outline-none focus:ring-1 focus:ring-blue-500
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const Avatar: React.FC<AvatarProps> = ({
|
|||||||
src={src}
|
src={src}
|
||||||
alt={name}
|
alt={name}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={`rounded-full object-cover shadow-xs cursor-pointer ${className}`}
|
className={`rounded-full object-cover shadow-sm cursor-pointer ${className}`}
|
||||||
style={avatarStyle}
|
style={avatarStyle}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -78,7 +78,7 @@ const Avatar: React.FC<AvatarProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={`rounded-full flex items-center justify-center text-white font-medium shadow-xs cursor-pointer ${className}`}
|
className={`rounded-full flex items-center justify-center text-white font-medium shadow-sm cursor-pointer ${className}`}
|
||||||
style={avatarStyle}
|
style={avatarStyle}
|
||||||
>
|
>
|
||||||
{name.charAt(0)?.toUpperCase() || '?'}
|
{name.charAt(0)?.toUpperCase() || '?'}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ const AvatarGroup: React.FC<AvatarGroupProps> = ({
|
|||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`rounded-full flex items-center justify-center text-white font-medium shadow-xs border-2 cursor-pointer ${
|
className={`rounded-full flex items-center justify-center text-white font-medium shadow-sm border-2 cursor-pointer ${
|
||||||
isDarkMode
|
isDarkMode
|
||||||
? 'bg-gray-600 border-gray-700'
|
? 'bg-gray-600 border-gray-700'
|
||||||
: 'bg-gray-400 border-white'
|
: 'bg-gray-400 border-white'
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const Button: React.FC<ButtonProps & React.ButtonHTMLAttributes<HTMLButtonElemen
|
|||||||
type = 'button',
|
type = 'button',
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const baseClasses = `inline-flex items-center justify-center font-medium transition-colors duration-200 focus:outline-hidden focus:ring-2 ${isDarkMode ? 'focus:ring-blue-400' : 'focus:ring-blue-500'} focus:ring-offset-1 ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`;
|
const baseClasses = `inline-flex items-center justify-center font-medium transition-colors duration-200 focus:outline-none focus:ring-2 ${isDarkMode ? 'focus:ring-blue-400' : 'focus:ring-blue-500'} focus:ring-offset-2 ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`;
|
||||||
|
|
||||||
const variantClasses = {
|
const variantClasses = {
|
||||||
text: isDarkMode
|
text: isDarkMode
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ const LabelsSelector: React.FC<LabelsSelectorProps> = ({
|
|||||||
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
||||||
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
||||||
}
|
}
|
||||||
focus:outline-hidden focus:ring-1 focus:ring-blue-500
|
focus:outline-none focus:ring-1 focus:ring-blue-500
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ const AssigneeDropdownContent: React.FC<AssigneeDropdownContentProps> = ({
|
|||||||
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
? 'bg-gray-700 border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500'
|
||||||
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500 focus:border-blue-500'
|
||||||
}
|
}
|
||||||
focus:outline-hidden focus:ring-1 focus:ring-blue-500
|
focus:outline-none focus:ring-1 focus:ring-blue-500
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ const FilterDropdown: React.FC<{
|
|||||||
? (isDarkMode ? 'bg-blue-600 text-white border-blue-500' : 'bg-blue-50 text-blue-800 border-blue-300 font-semibold')
|
? (isDarkMode ? 'bg-blue-600 text-white border-blue-500' : 'bg-blue-50 text-blue-800 border-blue-300 font-semibold')
|
||||||
: `${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText}`
|
: `${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText}`
|
||||||
}
|
}
|
||||||
hover:shadow-xs focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-1
|
hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
|
||||||
${isDarkMode ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'}
|
${isDarkMode ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'}
|
||||||
`}
|
`}
|
||||||
aria-expanded={isOpen}
|
aria-expanded={isOpen}
|
||||||
@@ -414,7 +414,7 @@ const FilterDropdown: React.FC<{
|
|||||||
|
|
||||||
{/* Dropdown Panel */}
|
{/* Dropdown Panel */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className={`absolute top-full left-0 z-50 mt-1 w-64 ${themeClasses.dropdownBg} rounded-md shadow-lg border ${themeClasses.dropdownBorder}`}>
|
<div className={`absolute top-full left-0 z-50 mt-1 w-64 ${themeClasses.dropdownBg} rounded-md shadow-sm border ${themeClasses.dropdownBorder}`}>
|
||||||
{/* Search Input */}
|
{/* Search Input */}
|
||||||
{section.searchable && (
|
{section.searchable && (
|
||||||
<div className={`p-2 border-b ${themeClasses.dividerBorder}`}>
|
<div className={`p-2 border-b ${themeClasses.dividerBorder}`}>
|
||||||
@@ -546,7 +546,7 @@ const SearchFilter: React.FC<{
|
|||||||
{!isExpanded ? (
|
{!isExpanded ? (
|
||||||
<button
|
<button
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}
|
||||||
className={`inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-md border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 ${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText} ${themeClasses.containerBg === 'bg-gray-800' ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'
|
className={`inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium rounded-md border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText} ${themeClasses.containerBg === 'bg-gray-800' ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<SearchOutlined className="w-3.5 h-3.5" />
|
<SearchOutlined className="w-3.5 h-3.5" />
|
||||||
@@ -579,7 +579,7 @@ const SearchFilter: React.FC<{
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="px-2.5 py-1.5 text-xs font-medium text-white bg-blue-500 rounded-md hover:bg-blue-600 focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 transition-colors duration-200"
|
className="px-2.5 py-1.5 text-xs font-medium text-white bg-blue-500 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors duration-200"
|
||||||
>
|
>
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
@@ -646,7 +646,7 @@ const FieldsDropdown: React.FC<{ themeClasses: any; isDarkMode: boolean }> = ({
|
|||||||
? (isDarkMode ? 'bg-blue-600 text-white border-blue-500' : 'bg-blue-50 text-blue-800 border-blue-300 font-semibold')
|
? (isDarkMode ? 'bg-blue-600 text-white border-blue-500' : 'bg-blue-50 text-blue-800 border-blue-300 font-semibold')
|
||||||
: `${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText}`
|
: `${themeClasses.buttonBg} ${themeClasses.buttonBorder} ${themeClasses.buttonText}`
|
||||||
}
|
}
|
||||||
hover:shadow-xs focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:ring-offset-1
|
hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
|
||||||
${isDarkMode ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'}
|
${isDarkMode ? 'focus:ring-offset-gray-900' : 'focus:ring-offset-white'}
|
||||||
`}
|
`}
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
@@ -666,7 +666,7 @@ const FieldsDropdown: React.FC<{ themeClasses: any; isDarkMode: boolean }> = ({
|
|||||||
|
|
||||||
{/* Dropdown Panel - matching FilterDropdown style */}
|
{/* Dropdown Panel - matching FilterDropdown style */}
|
||||||
{open && (
|
{open && (
|
||||||
<div className={`absolute top-full left-0 z-50 mt-1 w-64 ${themeClasses.dropdownBg} rounded-md shadow-lg border ${themeClasses.dropdownBorder}`}>
|
<div className={`absolute top-full left-0 z-50 mt-1 w-64 ${themeClasses.dropdownBg} rounded-md shadow-sm border ${themeClasses.dropdownBorder}`}>
|
||||||
{/* Options List */}
|
{/* Options List */}
|
||||||
<div className="max-h-48 overflow-y-auto">
|
<div className="max-h-48 overflow-y-auto">
|
||||||
{sortedFields.length === 0 ? (
|
{sortedFields.length === 0 ? (
|
||||||
@@ -1037,7 +1037,7 @@ const ImprovedTaskFilters: React.FC<ImprovedTaskFiltersProps> = ({
|
|||||||
}, [dispatch, projectId, position, showArchived]);
|
}, [dispatch, projectId, position, showArchived]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${themeClasses.containerBg} border ${themeClasses.containerBorder} rounded-md p-3 shadow-xs ${className}`}>
|
<div className={`${themeClasses.containerBg} border ${themeClasses.containerBorder} rounded-md p-3 shadow-sm ${className}`}>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
{/* Left Section - Main Filters */}
|
{/* Left Section - Main Filters */}
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ const TaskPhaseDropdown: React.FC<TaskPhaseDropdownProps> = ({
|
|||||||
|
|
||||||
{/* No Phase Color Indicator */}
|
{/* No Phase Color Indicator */}
|
||||||
<div
|
<div
|
||||||
className={`w-3 h-3 rounded-full shadow-xs border-2 ${
|
className={`w-3 h-3 rounded-full shadow-sm border-2 ${
|
||||||
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
||||||
}`}
|
}`}
|
||||||
style={{ backgroundColor: isDarkMode ? '#4b5563' : '#9ca3af' }}
|
style={{ backgroundColor: isDarkMode ? '#4b5563' : '#9ca3af' }}
|
||||||
@@ -234,7 +234,7 @@ const TaskPhaseDropdown: React.FC<TaskPhaseDropdownProps> = ({
|
|||||||
>
|
>
|
||||||
{/* Phase Color Indicator */}
|
{/* Phase Color Indicator */}
|
||||||
<div
|
<div
|
||||||
className={`w-3 h-3 rounded-full shadow-xs border-2 ${
|
className={`w-3 h-3 rounded-full shadow-sm border-2 ${
|
||||||
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
||||||
}`}
|
}`}
|
||||||
style={{ backgroundColor: getPhaseColor(phase) }}
|
style={{ backgroundColor: getPhaseColor(phase) }}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ const TaskPriorityDropdown: React.FC<TaskPriorityDropdownProps> = ({
|
|||||||
|
|
||||||
{/* Priority Color Indicator */}
|
{/* Priority Color Indicator */}
|
||||||
<div
|
<div
|
||||||
className={`w-3 h-3 rounded-full shadow-xs border-2 ${
|
className={`w-3 h-3 rounded-full shadow-sm border-2 ${
|
||||||
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
||||||
}`}
|
}`}
|
||||||
style={{ backgroundColor: getPriorityColor(priority) }}
|
style={{ backgroundColor: getPriorityColor(priority) }}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ const TaskStatusDropdown: React.FC<TaskStatusDropdownProps> = ({
|
|||||||
>
|
>
|
||||||
{/* Status Color Indicator */}
|
{/* Status Color Indicator */}
|
||||||
<div
|
<div
|
||||||
className={`w-3 h-3 rounded-full shadow-xs border-2 ${
|
className={`w-3 h-3 rounded-full shadow-sm border-2 ${
|
||||||
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
isDarkMode ? 'border-gray-800/30' : 'border-white/20'
|
||||||
}`}
|
}`}
|
||||||
style={{ backgroundColor: getStatusColor(status) }}
|
style={{ backgroundColor: getStatusColor(status) }}
|
||||||
|
|||||||
@@ -1,27 +1,10 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap')
|
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
|
||||||
layer(base);
|
@import url('./styles/customOverrides.css');
|
||||||
@import url('./styles/customOverrides.css') layer(base);
|
@import url('./styles/task-management.css');
|
||||||
@import url('./styles/task-management.css') layer(base);
|
|
||||||
|
|
||||||
@import 'tailwindcss';
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
/*
|
@tailwind utilities;
|
||||||
The default border color has changed to `currentcolor` in Tailwind CSS v4,
|
|
||||||
so we've added these compatibility styles to make sure everything still
|
|
||||||
looks the same as it did with Tailwind CSS v3.
|
|
||||||
|
|
||||||
If we ever want to remove these styles, we need to add an explicit border
|
|
||||||
color utility to any element that depends on these defaults.
|
|
||||||
*/
|
|
||||||
@layer base {
|
|
||||||
*,
|
|
||||||
::after,
|
|
||||||
::before,
|
|
||||||
::backdrop,
|
|
||||||
::file-selector-button {
|
|
||||||
border-color: var(--color-gray-200, currentcolor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-loading-container {
|
.app-loading-container {
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const TaskManagementDemo: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className="min-h-screen bg-gray-50">
|
<Layout className="min-h-screen bg-gray-50">
|
||||||
<Header className="bg-white shadow-xs">
|
<Header className="bg-white shadow-sm">
|
||||||
<div className="max-w-7xl mx-auto px-4">
|
<div className="max-w-7xl mx-auto px-4">
|
||||||
<Title level={2} className="mb-0 text-gray-800">
|
<Title level={2} className="mb-0 text-gray-800">
|
||||||
Enhanced Task Management System
|
Enhanced Task Management System
|
||||||
|
|||||||
29
worklenz-frontend/tailwind.config.js
Normal file
29
worklenz-frontend/tailwind.config.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
"./src/**/*.{js,jsx,ts,tsx}",
|
||||||
|
"./public/index.html"
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
sans: [
|
||||||
|
'-apple-system',
|
||||||
|
'BlinkMacSystemFont',
|
||||||
|
'"Inter"',
|
||||||
|
'Roboto',
|
||||||
|
'"Helvetica Neue"',
|
||||||
|
'Arial',
|
||||||
|
'"Noto Sans"',
|
||||||
|
'sans-serif',
|
||||||
|
'"Apple Color Emoji"',
|
||||||
|
'"Segoe UI Emoji"',
|
||||||
|
'"Segoe UI Symbol"',
|
||||||
|
'"Noto Color Emoji"'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
darkMode: 'class',
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user