fix: implement custom CSS sync spinner and update all components
- Replaced broken animate-spin Tailwind class with custom weekly-spinner CSS - Standardized loading indicators across Auth, Tasks, and Calendar settings - Fixed JSX syntax errors in several components
This commit is contained in:
parent
eb5065131a
commit
83d0d0b920
@ -2939,4 +2939,30 @@ h3 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Weekly App Spinner */
|
||||||
|
@keyframes weekly-spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekly-spinner {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 2px solid rgba(0, 0, 0, 0.1);
|
||||||
|
border-top-color: #3b82f6;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: weekly-spin 0.8s linear infinite;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekly-spinner-white {
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-top-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dark-mode .weekly-spinner {
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
border-top-color: #60a5fa;
|
||||||
|
}
|
||||||
|
|||||||
@ -141,10 +141,7 @@ const AuthForm: React.FC<AuthFormProps> = ({ type, onSubmit, isLoading, error })
|
|||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<span className="flex items-center">
|
<span className="flex items-center">
|
||||||
<svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-3"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Processing...
|
Processing...
|
||||||
</span>
|
</span>
|
||||||
) : type === 'signup' ? (
|
) : type === 'signup' ? (
|
||||||
@ -179,8 +176,8 @@ const AuthForm: React.FC<AuthFormProps> = ({ type, onSubmit, isLoading, error })
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div >
|
||||||
</div>
|
</div >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -248,10 +248,7 @@ const CalendarSettings: React.FC<CalendarSettingsProps> = ({
|
|||||||
>
|
>
|
||||||
{isSyncing[connection.id] ? (
|
{isSyncing[connection.id] ? (
|
||||||
<>
|
<>
|
||||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true">
|
<div className="weekly-spinner -ml-1 mr-2 inline-block"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Syncing...
|
Syncing...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@ -290,7 +287,8 @@ const CalendarSettings: React.FC<CalendarSettingsProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
<div className="connect-options mt-8 pt-6 border-t border-gray-200" role="region" aria-label="Connect more calendars">
|
<div className="connect-options mt-8 pt-6 border-t border-gray-200" role="region" aria-label="Connect more calendars">
|
||||||
<h3 className="text-xl font-semibold text-gray-800 mb-4" role="heading" aria-level={3}>Add More Calendars</h3>
|
<h3 className="text-xl font-semibold text-gray-800 mb-4" role="heading" aria-level={3}>Add More Calendars</h3>
|
||||||
@ -376,10 +374,7 @@ const CalendarSettings: React.FC<CalendarSettingsProps> = ({
|
|||||||
>
|
>
|
||||||
{isConnectingApple ? (
|
{isConnectingApple ? (
|
||||||
<>
|
<>
|
||||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-2"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Connecting...
|
Connecting...
|
||||||
</>
|
</>
|
||||||
) : 'Connect'}
|
) : 'Connect'}
|
||||||
@ -429,19 +424,17 @@ const CalendarSettings: React.FC<CalendarSettingsProps> = ({
|
|||||||
>
|
>
|
||||||
{isConnectingApple ? (
|
{isConnectingApple ? (
|
||||||
<>
|
<>
|
||||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-2"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Verifying...
|
Verifying...
|
||||||
</>
|
</>
|
||||||
) : 'Verify'}
|
) : 'Verify'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)
|
||||||
</div>
|
}
|
||||||
</div>
|
</div >
|
||||||
|
</div >
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div >
|
</div >
|
||||||
|
|||||||
@ -82,7 +82,7 @@ export const ImportListModal: React.FC<ImportListModalProps> = ({
|
|||||||
<div style={{ flex: 1, overflowY: 'auto', minHeight: '200px' }}>
|
<div style={{ flex: 1, overflowY: 'auto', minHeight: '200px' }}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
||||||
<Loader className="animate-spin" />
|
<div className="weekly-spinner"></div>
|
||||||
<span style={{ marginLeft: '8px' }}>Loading lists...</span>
|
<span style={{ marginLeft: '8px' }}>Loading lists...</span>
|
||||||
</div>
|
</div>
|
||||||
) : lists.length === 0 ? (
|
) : lists.length === 0 ? (
|
||||||
|
|||||||
@ -112,9 +112,8 @@ const TaskForm: React.FC<TaskFormProps> = ({ onSubmit, isLoading = false }) => {
|
|||||||
name="title"
|
name="title"
|
||||||
value={formData.title}
|
value={formData.title}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.title ? 'border-red-500' : 'border-gray-300'
|
||||||
errors.title ? 'border-red-500' : 'border-gray-300'
|
}`}
|
||||||
}`}
|
|
||||||
placeholder="What needs to be done?"
|
placeholder="What needs to be done?"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
@ -147,9 +146,8 @@ const TaskForm: React.FC<TaskFormProps> = ({ onSubmit, isLoading = false }) => {
|
|||||||
name="startTime"
|
name="startTime"
|
||||||
value={formData.startTime}
|
value={formData.startTime}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.startTime ? 'border-red-500' : 'border-gray-300'
|
||||||
errors.startTime ? 'border-red-500' : 'border-gray-300'
|
}`}
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
{errors.startTime && <p className="mt-1 text-sm text-red-600">{errors.startTime}</p>}
|
{errors.startTime && <p className="mt-1 text-sm text-red-600">{errors.startTime}</p>}
|
||||||
</div>
|
</div>
|
||||||
@ -164,9 +162,8 @@ const TaskForm: React.FC<TaskFormProps> = ({ onSubmit, isLoading = false }) => {
|
|||||||
name="endTime"
|
name="endTime"
|
||||||
value={formData.endTime}
|
value={formData.endTime}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
|
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.endTime ? 'border-red-500' : 'border-gray-300'
|
||||||
errors.endTime ? 'border-red-500' : 'border-gray-300'
|
}`}
|
||||||
}`}
|
|
||||||
/>
|
/>
|
||||||
{errors.endTime && <p className="mt-1 text-sm text-red-600">{errors.endTime}</p>}
|
{errors.endTime && <p className="mt-1 text-sm text-red-600">{errors.endTime}</p>}
|
||||||
</div>
|
</div>
|
||||||
@ -196,25 +193,21 @@ const TaskForm: React.FC<TaskFormProps> = ({ onSubmit, isLoading = false }) => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
className={`w-full py-2 px-4 rounded-md text-white font-medium transition-colors ${
|
className={`w-full py-2 px-4 rounded-md text-white font-medium transition-colors ${isLoading
|
||||||
isLoading
|
? 'bg-blue-400 cursor-not-allowed'
|
||||||
? 'bg-blue-400 cursor-not-allowed'
|
: 'bg-blue-600 hover:bg-blue-700'
|
||||||
: 'bg-blue-600 hover:bg-blue-700'
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<span className="flex items-center justify-center">
|
<span className="flex items-center justify-center">
|
||||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-2"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Adding Task...
|
Adding Task...
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
'Add Task'
|
'Add Task'
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -146,10 +146,7 @@ export default function TaskItem({ task, onToggleComplete, onDelete, onEdit, onT
|
|||||||
aria-label="Delete task"
|
aria-label="Delete task"
|
||||||
>
|
>
|
||||||
{isDeleting ? (
|
{isDeleting ? (
|
||||||
<svg className="animate-spin h-5 w-5 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||||
<path fillRule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clipRule="evenodd" />
|
<path fillRule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clipRule="evenodd" />
|
||||||
|
|||||||
@ -3312,10 +3312,7 @@ export default function WeeklyView() {
|
|||||||
{/* Week & Year */}
|
{/* Week & Year */}
|
||||||
<div className="whitespace-nowrap flex items-center gap-2">
|
<div className="whitespace-nowrap flex items-center gap-2">
|
||||||
{(isLoading || isSyncing || syncStatus === "syncing") && (
|
{(isLoading || isSyncing || syncStatus === "syncing") && (
|
||||||
<div
|
<div className="weekly-spinner" title="Syncing..."></div>
|
||||||
className="animate-spin rounded-full h-4 w-4 border-2 border-gray-300 border-t-blue-600 mr-2"
|
|
||||||
title="Syncing..."
|
|
||||||
></div>
|
|
||||||
)}
|
)}
|
||||||
<span style={{
|
<span style={{
|
||||||
fontFamily: profile.cwFontFamily || "Inter",
|
fontFamily: profile.cwFontFamily || "Inter",
|
||||||
@ -9688,26 +9685,7 @@ function SettingsSidebar({
|
|||||||
>
|
>
|
||||||
{isConnectingAppleCal ? (
|
{isConnectingAppleCal ? (
|
||||||
<>
|
<>
|
||||||
<svg
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-2"></div>
|
||||||
className="animate-spin -ml-1 mr-2 h-4 w-4 text-white"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
className="opacity-25"
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="4"
|
|
||||||
></circle>
|
|
||||||
<path
|
|
||||||
className="opacity-75"
|
|
||||||
fill="currentColor"
|
|
||||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
Connecting...
|
Connecting...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -128,10 +128,7 @@ const EmailAuthForm: React.FC<EmailAuthFormProps> = ({ type, onSubmit, isLoading
|
|||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<span className="flex items-center">
|
<span className="flex items-center">
|
||||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div className="weekly-spinner weekly-spinner-white -ml-1 mr-2"></div>
|
||||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
|
||||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
||||||
</svg>
|
|
||||||
Processing...
|
Processing...
|
||||||
</span>
|
</span>
|
||||||
) : type === 'signup' ? (
|
) : type === 'signup' ? (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user