summaryrefslogtreecommitdiffstats
path: root/themes/danix-xyz-hacker/assets/css/main.css
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-04-16 16:53:21 +0200
committerDanilo M. <danix@danix.xyz>2026-04-16 16:53:21 +0200
commit9877591a86cb66917c35d5b58190270061d7261a (patch)
tree412b6bf34237f423d0a06a33c475147f7f5692a8 /themes/danix-xyz-hacker/assets/css/main.css
parenta6c9e54b7465013797400f96aa81b17344f56e28 (diff)
downloaddanixxyz-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.css474
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);
+}