summaryrefslogtreecommitdiffstats
path: root/themes
diff options
context:
space:
mode:
Diffstat (limited to 'themes')
-rw-r--r--themes/danix-xyz-hacker/assets/js/form-components.js91
-rw-r--r--themes/danix-xyz-hacker/layouts/partials/form-components.html219
-rw-r--r--themes/danix-xyz-hacker/layouts/partials/toast-container.html13
3 files changed, 323 insertions, 0 deletions
diff --git a/themes/danix-xyz-hacker/assets/js/form-components.js b/themes/danix-xyz-hacker/assets/js/form-components.js
new file mode 100644
index 0000000..35a5f27
--- /dev/null
+++ b/themes/danix-xyz-hacker/assets/js/form-components.js
@@ -0,0 +1,91 @@
+// Form component utilities and Alpine.js data
+
+export function formComponentsData() {
+ return {
+ // Modal states
+ showAlertModal: false,
+ showConfirmModal: false,
+ showContentModal: false,
+
+ // Toast notification state
+ toasts: [],
+
+ // Handle confirm modal action
+ handleConfirm() {
+ this.showConfirmModal = false;
+ this.showToast('success', 'Action confirmed!');
+ },
+
+ // Show toast notification
+ showToast(type = 'success', message = null) {
+ const messages = {
+ success: 'Operation completed successfully!',
+ error: 'An error occurred. Please try again.',
+ info: 'Here is some information.',
+ warning: 'Please be careful with this action.'
+ };
+
+ const toastMessage = message || messages[type] || messages.success;
+ const toastId = Date.now();
+
+ // Add toast to list
+ this.toasts.push({
+ id: toastId,
+ type: type,
+ message: toastMessage
+ });
+
+ // Auto-remove after 5 seconds
+ setTimeout(() => {
+ this.toasts = this.toasts.filter(t => t.id !== toastId);
+ }, 5000);
+ },
+
+ // Remove toast manually
+ removeToast(id) {
+ this.toasts = this.toasts.filter(t => t.id !== id);
+ },
+
+ // Form validation utilities
+ validateEmail(email) {
+ const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ return regex.test(email);
+ },
+
+ validatePassword(password) {
+ return password.length >= 8;
+ },
+
+ // Auto-expand textarea
+ autoExpandTextarea(event) {
+ const textarea = event.target;
+ textarea.style.height = 'auto';
+ textarea.style.height = (textarea.scrollHeight) + 'px';
+ }
+ };
+}
+
+// Toast container component for Alpine.js
+export function renderToastContainer(Alpine) {
+ if (!Alpine) return;
+
+ // This can be used in templates via Alpine
+ window.formUtils = {
+ formatCharCount(current, max) {
+ if (max) {
+ return `${current}/${max}`;
+ }
+ return current;
+ },
+
+ isCharCountWarning(current, max) {
+ if (!max) return false;
+ return current > (max * 0.8);
+ },
+
+ isCharCountError(current, max) {
+ if (!max) return false;
+ return current >= max;
+ }
+ };
+}
diff --git a/themes/danix-xyz-hacker/layouts/partials/form-components.html b/themes/danix-xyz-hacker/layouts/partials/form-components.html
new file mode 100644
index 0000000..9a69d43
--- /dev/null
+++ b/themes/danix-xyz-hacker/layouts/partials/form-components.html
@@ -0,0 +1,219 @@
+{{ define "form-components" }}
+
+<!-- ============================================
+ FORM INPUT EXAMPLES
+ ============================================ -->
+
+<section class="my-12 space-y-8">
+ <h2>Form Components</h2>
+
+ <!-- Basic Form Group -->
+ <div class="form-group">
+ <label for="input-text">Text Input</label>
+ <input type="text" id="input-text" class="form-input" placeholder="Enter text...">
+ </div>
+
+ <!-- Form Group with Error -->
+ <div class="form-group error">
+ <label for="input-email">Email (with error)</label>
+ <input type="email" id="input-email" class="form-input error" value="invalid-email">
+ <div class="form-error">{{ i18n "form_invalid_email" }}</div>
+ </div>
+
+ <!-- Form Group with Help Text -->
+ <div class="form-group">
+ <label for="input-password" class="">Password</label>
+ <input type="password" id="input-password" class="form-input" placeholder="••••••">
+ <div class="form-group-help">{{ i18n "form_password_help" | default "Must be at least 8 characters" }}</div>
+ </div>
+
+ <!-- Disabled Input -->
+ <div class="form-group">
+ <label for="input-disabled">Disabled Input</label>
+ <input type="text" id="input-disabled" class="form-input" value="Cannot edit" disabled>
+ </div>
+
+ <!-- ============================================
+ TEXTAREA EXAMPLES
+ ============================================ -->
+
+ <div class="form-group">
+ <label for="textarea-message">Message</label>
+ <textarea id="textarea-message" class="form-textarea" placeholder="Enter your message..."></textarea>
+ </div>
+
+ <!-- ============================================
+ SELECT EXAMPLES
+ ============================================ -->
+
+ <div class="form-group">
+ <label for="select-option">Select an option</label>
+ <select id="select-option" class="form-select">
+ <option>Choose...</option>
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+ </select>
+ </div>
+
+ <!-- ============================================
+ CHECKBOX EXAMPLES
+ ============================================ -->
+
+ <div class="form-group">
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox">
+ <span>{{ i18n "form_agree_terms" | default "I agree to the terms" }}</span>
+ </label>
+ </div>
+
+ <!-- Multiple Checkboxes -->
+ <div class="form-group space-y-2">
+ <p class="font-semibold">{{ i18n "form_select_interests" | default "Select your interests" }}</p>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox" name="interests">
+ <span>{{ i18n "form_interest_tech" | default "Technology" }}</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="checkbox" class="form-checkbox" name="interests">
+ <span>{{ i18n "form_interest_design" | default "Design" }}</span>
+ </label>
+ </div>
+
+ <!-- ============================================
+ RADIO BUTTON EXAMPLES
+ ============================================ -->
+
+ <div class="form-group space-y-2">
+ <p class="font-semibold">{{ i18n "form_select_preference" | default "Select a preference" }}</p>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="radio" name="preference" class="form-radio">
+ <span>{{ i18n "form_option_a" | default "Option A" }}</span>
+ </label>
+ <label class="flex items-center gap-3 cursor-pointer">
+ <input type="radio" name="preference" class="form-radio">
+ <span>{{ i18n "form_option_b" | default "Option B" }}</span>
+ </label>
+ </div>
+
+ <!-- ============================================
+ FORM ROWS (MULTI-COLUMN)
+ ============================================ -->
+
+ <div class="form-row">
+ <div class="form-group">
+ <label for="first-name">{{ i18n "form_first_name" | default "First Name" }}</label>
+ <input type="text" id="first-name" class="form-input" placeholder="John">
+ </div>
+ <div class="form-group">
+ <label for="last-name">{{ i18n "form_last_name" | default "Last Name" }}</label>
+ <input type="text" id="last-name" class="form-input" placeholder="Doe">
+ </div>
+ </div>
+
+ <!-- ============================================
+ INLINE FORMS
+ ============================================ -->
+
+ <div class="form-inline">
+ <div class="form-group">
+ <label for="search-input">{{ i18n "form_search" | default "Search" }}</label>
+ <input type="text" id="search-input" class="form-input" placeholder="Type to search...">
+ </div>
+ <button class="btn btn-primary">{{ i18n "form_search_btn" | default "Search" }}</button>
+ </div>
+
+ <!-- ============================================
+ MODALS (DEMO BUTTONS)
+ ============================================ -->
+
+ <div class="space-y-3 mt-8">
+ <h3>Modal Examples</h3>
+ <button class="btn btn-primary" @click="showAlertModal = true">{{ i18n "form_open_alert" | default "Open Alert Modal" }}</button>
+ <button class="btn btn-secondary" @click="showConfirmModal = true">{{ i18n "form_open_confirm" | default "Open Confirm Modal" }}</button>
+ <button class="btn btn-outline" @click="showContentModal = true">{{ i18n "form_open_content" | default "Open Content Modal" }}</button>
+ </div>
+
+ <!-- ============================================
+ NOTIFICATIONS (DEMO BUTTONS)
+ ============================================ -->
+
+ <div class="space-y-3 mt-8">
+ <h3>Notifications</h3>
+ <button class="btn btn-primary btn-sm" @click="showToast('success')">Success Toast</button>
+ <button class="btn btn-secondary btn-sm" @click="showToast('error')">Error Toast</button>
+ <button class="btn btn-sm" style="background-color: #3b82f6; color: white;" @click="showToast('info')">Info Toast</button>
+ <button class="btn btn-sm" style="background-color: #f59e0b; color: white;" @click="showToast('warning')">Warning Toast</button>
+ </div>
+
+</section>
+
+<!-- ============================================
+ ALERT MODAL
+ ============================================ -->
+
+<div class="modal" :class="{ active: showAlertModal }" x-show="showAlertModal">
+ <div class="modal-backdrop" @click="showAlertModal = false"></div>
+ <div class="modal-content modal-sm">
+ <div class="modal-header">
+ <h3 class="modal-title">{{ i18n "form_alert_title" | default "Alert" }}</h3>
+ <div class="modal-close" @click="showAlertModal = false"></div>
+ </div>
+ <div class="modal-body">
+ <p>{{ i18n "form_alert_message" | default "This is an alert modal. Click OK to dismiss." }}</p>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" @click="showAlertModal = false">{{ i18n "form_ok" | default "OK" }}</button>
+ </div>
+ </div>
+</div>
+
+<!-- ============================================
+ CONFIRM MODAL
+ ============================================ -->
+
+<div class="modal" :class="{ active: showConfirmModal }" x-show="showConfirmModal">
+ <div class="modal-backdrop" @click="showConfirmModal = false"></div>
+ <div class="modal-content modal-sm">
+ <div class="modal-header">
+ <h3 class="modal-title">{{ i18n "form_confirm_title" | default "Confirm Action" }}</h3>
+ <div class="modal-close" @click="showConfirmModal = false"></div>
+ </div>
+ <div class="modal-body">
+ <p>{{ i18n "form_confirm_message" | default "Are you sure you want to continue?" }}</p>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-outline" @click="showConfirmModal = false">{{ i18n "form_cancel" | default "Cancel" }}</button>
+ <button class="btn btn-primary" @click="handleConfirm()">{{ i18n "form_confirm" | default "Confirm" }}</button>
+ </div>
+ </div>
+</div>
+
+<!-- ============================================
+ CONTENT MODAL
+ ============================================ -->
+
+<div class="modal" :class="{ active: showContentModal }" x-show="showContentModal">
+ <div class="modal-backdrop" @click="showContentModal = false"></div>
+ <div class="modal-content modal-md">
+ <div class="modal-header">
+ <h3 class="modal-title">{{ i18n "form_content_title" | default "Modal with Content" }}</h3>
+ <div class="modal-close" @click="showContentModal = false"></div>
+ </div>
+ <div class="modal-body">
+ <p>{{ i18n "form_content_message" | default "This modal contains detailed content. You can add forms, lists, or any HTML here." }}</p>
+ <div class="mt-4">
+ <div class="form-group">
+ <label for="modal-input">Input in Modal</label>
+ <input type="text" id="modal-input" class="form-input" placeholder="Type here...">
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-outline" @click="showContentModal = false">{{ i18n "form_close" | default "Close" }}</button>
+ <button class="btn btn-primary">{{ i18n "form_save" | default "Save" }}</button>
+ </div>
+ </div>
+</div>
+
+{{ end }}
diff --git a/themes/danix-xyz-hacker/layouts/partials/toast-container.html b/themes/danix-xyz-hacker/layouts/partials/toast-container.html
new file mode 100644
index 0000000..1c5fbf2
--- /dev/null
+++ b/themes/danix-xyz-hacker/layouts/partials/toast-container.html
@@ -0,0 +1,13 @@
+{{ define "toast-container" }}
+
+<!-- Toast notification container with Alpine.js integration -->
+<div class="toast-container" x-data="formComponentsData()">
+ <template x-for="toast in toasts" :key="toast.id">
+ <div class="toast" :class="`toast-${toast.type}`" x-show="toasts.length > 0">
+ <span x-text="toast.message"></span>
+ <div class="toast-close" @click="removeToast(toast.id)"></div>
+ </div>
+ </template>
+</div>
+
+{{ end }}