diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-16 16:53:21 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-16 16:53:21 +0200 |
| commit | 9877591a86cb66917c35d5b58190270061d7261a (patch) | |
| tree | 412b6bf34237f423d0a06a33c475147f7f5692a8 /themes/danix-xyz-hacker/assets/css/main.css | |
| parent | a6c9e54b7465013797400f96aa81b17344f56e28 (diff) | |
| download | danixxyz-9877591a86cb66917c35d5b58190270061d7261a.tar.gz danixxyz-9877591a86cb66917c35d5b58190270061d7261a.zip | |
feat: add form component styles (inputs, textarea, checkbox, radio)
Diffstat (limited to 'themes/danix-xyz-hacker/assets/css/main.css')
| -rw-r--r-- | themes/danix-xyz-hacker/assets/css/main.css | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/themes/danix-xyz-hacker/assets/css/main.css b/themes/danix-xyz-hacker/assets/css/main.css index 9e5c86a..19584bf 100644 --- a/themes/danix-xyz-hacker/assets/css/main.css +++ b/themes/danix-xyz-hacker/assets/css/main.css @@ -595,3 +595,477 @@ article.border.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { border-color: var(--border); box-shadow: 0 0 20px var(--accent-glow); } + +/* ============================================ + FORM COMPONENTS (Week 4) + ============================================ */ + +/* Form input base styles */ +.form-input, +.form-textarea, +.form-select { + @apply w-full px-4 py-2 rounded border border-border bg-bg2 text-text font-body transition-all duration-200; +} + +/* Input placeholder styling */ +.form-input::placeholder, +.form-textarea::placeholder { + color: var(--text-dim); + opacity: 0.7; +} + +/* Input focus state */ +.form-input:focus, +.form-textarea:focus, +.form-select:focus { + @apply outline-none border-accent ring-2 ring-accent ring-offset-2; + ring-offset-color: var(--bg); + border-color: var(--accent); +} + +/* Input invalid/error state */ +.form-input:invalid, +.form-textarea:invalid, +.form-select:invalid, +.form-input.error, +.form-textarea.error, +.form-select.error { + @apply border-red-500 ring-red-500; +} + +.form-input:invalid:focus, +.form-textarea:invalid:focus, +.form-select:invalid:focus { + @apply ring-red-500 border-red-500; + ring-offset-color: var(--bg); +} + +/* Input disabled state */ +.form-input:disabled, +.form-textarea:disabled, +.form-select:disabled { + @apply opacity-50 cursor-not-allowed bg-muted; +} + +/* Textarea specific */ +.form-textarea { + @apply min-h-32; + resize: vertical; +} + +.form-textarea.auto-expand { + resize: none; + overflow-y: hidden; +} + +/* Select dropdown */ +.form-select { + cursor: pointer; + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23a855f7' d='M6 9L1 4h10z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 0.75rem center; + padding-right: 2.5rem; +} + +html.theme-light .form-select { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%239333ea' d='M6 9L1 4h10z'/%3E%3C/svg%3E"); +} + +/* Checkbox and radio button base */ +.form-checkbox, +.form-radio { + @apply w-5 h-5 cursor-pointer accent-accent transition-all duration-200; + appearance: none; + border: 2px solid var(--border); + border-radius: 0.375rem; + flex-shrink: 0; +} + +.form-radio { + border-radius: 50%; +} + +/* Checkbox/radio focus state */ +.form-checkbox:focus-visible, +.form-radio:focus-visible { + @apply outline-none ring-2 ring-accent ring-offset-2; + ring-offset-color: var(--bg); +} + +/* Checkbox/radio checked state */ +.form-checkbox:checked, +.form-radio:checked { + background-color: var(--accent); + border-color: var(--accent); + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.form-radio:checked { + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3.5'/%3E%3C/svg%3E"); +} + +/* Checkbox/radio disabled state */ +.form-checkbox:disabled, +.form-radio:disabled { + @apply opacity-50 cursor-not-allowed; + border-color: var(--muted); +} + +/* Form group layout */ +.form-group { + @apply space-y-2; +} + +.form-group label { + @apply block text-sm font-semibold text-text; +} + +.form-group.required label::after { + content: ' *'; + color: #ef4444; +} + +.form-group-input { + @apply relative; +} + +.form-group-help { + @apply text-xs text-text-dim; +} + +.form-group.error .form-group-help { + @apply text-red-500; +} + +.form-error { + @apply text-sm text-red-500 mt-1; +} + +/* Form layout utilities */ +.form-row { + @apply flex flex-col md:flex-row gap-4; +} + +.form-row > .form-group { + @apply flex-1; +} + +.form-inline { + @apply flex flex-col sm:flex-row items-end gap-4; +} + +.form-inline .form-group { + @apply flex-1; +} + +.form-inline .btn { + @apply h-10; +} + +/* Character count indicator */ +.form-char-count { + @apply text-xs text-text-dim text-right; +} + +.form-char-count.warning { + @apply text-amber-500; +} + +.form-char-count.error { + @apply text-red-500; +} + +/* ============================================ + MODAL COMPONENTS (Week 4) + ============================================ */ + +/* Modal backdrop */ +.modal-backdrop { + @apply fixed inset-0 bg-black/50 opacity-0 invisible transition-all duration-300 z-40; + backdrop-filter: blur(2px); +} + +.modal-backdrop.active { + @apply opacity-100 visible; +} + +/* Modal container */ +.modal { + @apply fixed inset-0 flex items-center justify-center opacity-0 invisible transition-all duration-300 z-50 p-4; + pointer-events: none; +} + +.modal.active { + @apply opacity-100 visible; + pointer-events: auto; +} + +.modal.active .modal-backdrop { + @apply opacity-100 visible; + pointer-events: auto; +} + +/* Modal content box */ +.modal-content { + @apply bg-bg2 border border-border rounded-lg shadow-2xl max-w-lg w-full max-h-[90vh] flex flex-col; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); + animation: modalSlideUp 0.3s ease-out; +} + +@keyframes modalSlideUp { + from { + transform: translateY(20px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +/* Modal header */ +.modal-header { + @apply flex items-start justify-between gap-4 p-6 border-b border-border; +} + +.modal-title { + @apply text-xl font-bold text-text; +} + +.modal-close { + @apply flex items-center justify-center w-8 h-8 rounded hover:bg-surface cursor-pointer transition-colors; +} + +.modal-close::before, +.modal-close::after { + content: ''; + @apply absolute w-5 h-0.5 bg-text-dim; +} + +.modal-close::before { + transform: rotate(45deg); +} + +.modal-close::after { + transform: rotate(-45deg); +} + +.modal-close:hover::before, +.modal-close:hover::after { + @apply bg-accent; +} + +/* Modal body */ +.modal-body { + @apply flex-1 overflow-y-auto p-6 space-y-4; +} + +/* Modal footer */ +.modal-footer { + @apply flex items-center justify-end gap-3 p-6 border-t border-border; +} + +/* Modal sizes */ +.modal-content.modal-sm { + @apply max-w-sm; +} + +.modal-content.modal-md { + @apply max-w-md; +} + +.modal-content.modal-lg { + @apply max-w-2xl; +} + +/* Modal variants */ +.modal-content.modal-alert { + @apply max-w-sm; +} + +.modal-content.modal-confirm { + @apply max-w-sm; +} + +/* Modal button styling */ +.modal-footer .btn { + @apply min-w-[100px]; +} + +/* ============================================ + INTERACTIVE PATTERNS (Week 4) + ============================================ */ + +/* Loading spinner */ +.spinner { + @apply inline-block; + width: 1rem; + height: 1rem; + border: 2px solid var(--border); + border-top-color: var(--accent); + border-radius: 50%; + animation: spin 0.6s linear infinite; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +.spinner-sm { + width: 0.75rem; + height: 0.75rem; + border-width: 1.5px; +} + +.spinner-lg { + width: 1.5rem; + height: 1.5rem; + border-width: 3px; +} + +/* Button with spinner */ +.btn:disabled .spinner { + @apply inline-block mr-2; +} + +/* Toast notification container */ +.toast-container { + @apply fixed bottom-0 right-0 p-4 space-y-3 max-w-sm z-50; +} + +@media (max-width: 640px) { + .toast-container { + @apply left-0 right-0 px-4; + } +} + +/* Toast base */ +.toast { + @apply flex items-start gap-3 p-4 rounded-lg border border-border shadow-lg; + animation: slideInUp 0.3s ease-out; + background-color: var(--bg2); + color: var(--text); +} + +@keyframes slideInUp { + from { + transform: translateY(100%); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} + +/* Toast variants */ +.toast-success { + border-color: #10b981; + background-color: rgba(16, 185, 129, 0.1); +} + +.toast-success::before { + content: '✓'; + color: #10b981; + font-weight: bold; + flex-shrink: 0; +} + +.toast-error { + border-color: #ef4444; + background-color: rgba(239, 68, 68, 0.1); +} + +.toast-error::before { + content: '✕'; + color: #ef4444; + font-weight: bold; + flex-shrink: 0; +} + +.toast-info { + border-color: #3b82f6; + background-color: rgba(59, 130, 246, 0.1); +} + +.toast-info::before { + content: 'ℹ'; + color: #3b82f6; + flex-shrink: 0; +} + +.toast-warning { + border-color: #f59e0b; + background-color: rgba(245, 158, 11, 0.1); +} + +.toast-warning::before { + content: '⚠'; + color: #f59e0b; + flex-shrink: 0; +} + +.toast-close { + @apply ml-auto flex-shrink-0 w-6 h-6 flex items-center justify-center cursor-pointer hover:bg-surface rounded transition-colors; +} + +/* Tooltip */ +.tooltip { + @apply relative inline-block; +} + +.tooltip-text { + @apply absolute bg-bg2 text-text-dim text-xs rounded px-2 py-1 whitespace-nowrap pointer-events-none opacity-0 invisible transition-all duration-200; + z-index: 50; + bottom: 125%; + left: 50%; + transform: translateX(-50%); +} + +.tooltip:hover .tooltip-text { + @apply opacity-100 visible; +} + +.tooltip-text::after { + content: ''; + @apply absolute w-2 h-2 bg-bg2; + bottom: -4px; + left: 50%; + transform: translateX(-50%) rotate(45deg); +} + +/* Tooltip directions */ +.tooltip-bottom .tooltip-text { + @apply top-[125%] bottom-auto; +} + +.tooltip-bottom .tooltip-text::after { + @apply top-[-4px] bottom-auto; + transform: translateX(-50%) rotate(225deg); +} + +.tooltip-left .tooltip-text { + @apply left-auto right-[125%]; + transform: none; +} + +.tooltip-left .tooltip-text::after { + @apply left-auto right-[-4px]; + transform: rotate(135deg); +} + +.tooltip-right .tooltip-text { + @apply left-[125%]; + transform: none; +} + +.tooltip-right .tooltip-text::after { + @apply left-[-4px] right-auto; + transform: rotate(315deg); +} |
