إطار Tailwind CSS

بناء النماذج والنوافذ المنبثقة

25 دقيقة الدرس 30 من 35

بناء النماذج والنوافذ المنبثقة

أتقن بناء نماذج ونوافذ منبثقة يمكن الوصول إليها وجميلة مع Tailwind CSS. تعلم أنماط التحقق، تنسيق المدخلات، تراكبات النوافذ المنبثقة، وأفضل الممارسات لتفاعل المستخدم.

هيكل النموذج الأساسي

ابدأ بـ HTML دلالي وتنسيق Tailwind لعناصر النموذج:

نموذج اتصال بسيط

<form class="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg">
  <h2 class="text-2xl font-bold text-gray-900 mb-6">Contact Us</h2>

  <!-- حقل الاسم -->
  <div class="mb-4">
    <label for="name" class="block text-sm font-medium text-gray-700 mb-2">
      Full Name
    </label>
    <input
      type="text"
      id="name"
      name="name"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
      placeholder="John Doe"
    >
  </div>

  <!-- حقل البريد الإلكتروني -->
  <div class="mb-4">
    <label for="email" class="block text-sm font-medium text-gray-700 mb-2">
      Email Address
    </label>
    <input
      type="email"
      id="email"
      name="email"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
      placeholder="john@example.com"
    >
  </div>

  <!-- حقل الرسالة -->
  <div class="mb-6">
    <label for="message" class="block text-sm font-medium text-gray-700 mb-2">
      Message
    </label>
    <textarea
      id="message"
      name="message"
      rows="4"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
      placeholder="Your message here..."
    ></textarea>
  </div>

  <!-- زر الإرسال -->
  <button
    type="submit"
    class="w-full bg-blue-600 text-white font-semibold py-3 px-6 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"
  >
    Send Message
  </button>
</form>
حالات التركيز: قم دائماً بتضمين focus:outline-none مع focus:ring-2 لإزالة الحدود الافتراضية وإضافة حلقة تركيز مخصصة. هذا يحسن كل من الجماليات وإمكانية الوصول.

تنسيق التحقق من النموذج

أضف ردود فعل بصرية للحالات الصحيحة، غير الصحيحة، والمعطلة:

نموذج مع حالات التحقق

<form class="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg">
  <!-- إدخال صحيح -->
  <div class="mb-4">
    <label for="valid-email" class="block text-sm font-medium text-gray-700 mb-2">
      Email (Valid)
    </label>
    <div class="relative">
      <input
        type="email"
        id="valid-email"
        class="w-full px-4 py-2 pr-10 border-2 border-green-500 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500"
        value="user@example.com"
      >
      <div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
        <svg class="h-5 w-5 text-green-500" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
        </svg>
      </div>
    </div>
    <p class="mt-1 text-sm text-green-600">Looks good!</p>
  </div>

  <!-- إدخال غير صحيح -->
  <div class="mb-4">
    <label for="invalid-email" class="block text-sm font-medium text-gray-700 mb-2">
      Email (Invalid)
    </label>
    <div class="relative">
      <input
        type="email"
        id="invalid-email"
        class="w-full px-4 py-2 pr-10 border-2 border-red-500 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500"
        value="invalid-email"
      >
      <div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
        <svg class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
        </svg>
      </div>
    </div>
    <p class="mt-1 text-sm text-red-600">Please enter a valid email address.</p>
  </div>

  <!-- إدخال معطل -->
  <div class="mb-4">
    <label for="disabled-input" class="block text-sm font-medium text-gray-400 mb-2">
      Disabled Field
    </label>
    <input
      type="text"
      id="disabled-input"
      disabled
      class="w-full px-4 py-2 bg-gray-100 border border-gray-300 rounded-lg text-gray-500 cursor-not-allowed"
      value="Cannot edit this"
    >
  </div>
</form>
أيقونات الخطأ: ضع أيقونات التحقق بشكل مطلق داخل حاوية نسبية. استخدم pr-10 على المدخل لإفساح المجال للأيقونة، و pointer-events-none على الأيقونة للسماح بالنقر من خلالها.

نموذج تسجيل الدخول مع تذكرني

ابنِ نموذج تسجيل دخول كامل مع خانة اختيار ورابط نسيت كلمة المرور:

نموذج تسجيل دخول احترافي

<div class="min-h-screen flex items-center justify-center bg-gray-100 py-12 px-4">
  <div class="max-w-md w-full space-y-8 bg-white p-8 rounded-xl shadow-lg">
    <div class="text-center">
      <h2 class="text-3xl font-bold text-gray-900">Sign in to your account</h2>
      <p class="mt-2 text-sm text-gray-600">
        Or
        <a href="#" class="font-medium text-blue-600 hover:text-blue-500">
          start your 14-day free trial
        </a>
      </p>
    </div>

    <form class="mt-8 space-y-6">
      <div class="space-y-4">
        <!-- البريد الإلكتروني -->
        <div>
          <label for="login-email" class="block text-sm font-medium text-gray-700 mb-1">
            Email address
          </label>
          <input
            id="login-email"
            name="email"
            type="email"
            required
            class="appearance-none relative block w-full px-3 py-2 border border-gray-300 rounded-lg placeholder-gray-400 text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            placeholder="Email address"
          >
        </div>

        <!-- كلمة المرور -->
        <div>
          <label for="password" class="block text-sm font-medium text-gray-700 mb-1">
            Password
          </label>
          <input
            id="password"
            name="password"
            type="password"
            required
            class="appearance-none relative block w-full px-3 py-2 border border-gray-300 rounded-lg placeholder-gray-400 text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            placeholder="Password"
          >
        </div>
      </div>

      <!-- تذكرني ونسيت كلمة المرور -->
      <div class="flex items-center justify-between">
        <div class="flex items-center">
          <input
            id="remember-me"
            name="remember-me"
            type="checkbox"
            class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded cursor-pointer"
          >
          <label for="remember-me" class="ml-2 block text-sm text-gray-900 cursor-pointer">
            Remember me
          </label>
        </div>

        <div class="text-sm">
          <a href="#" class="font-medium text-blue-600 hover:text-blue-500">
            Forgot your password?
          </a>
        </div>
      </div>

      <!-- زر الإرسال -->
      <button
        type="submit"
        class="group relative w-full flex justify-center py-3 px-4 border border-transparent text-sm font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
      >
        Sign in
      </button>

      <!-- تسجيل الدخول الاجتماعي -->
      <div class="mt-6">
        <div class="relative">
          <div class="absolute inset-0 flex items-center">
            <div class="w-full border-t border-gray-300"></div>
          </div>
          <div class="relative flex justify-center text-sm">
            <span class="px-2 bg-white text-gray-500">Or continue with</span>
          </div>
        </div>

        <div class="mt-6 grid grid-cols-2 gap-3">
          <button type="button" class="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-lg shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
            <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
              <path fill-rule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z" clip-rule="evenodd"></path>
            </svg>
            <span class="ml-2">GitHub</span>
          </button>

          <button type="button" class="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-lg shadow-sm bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
            <svg class="w-5 h-5 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
              <path d="M6.29 18.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0020 3.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.073 4.073 0 01.8 7.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 010 16.407a11.616 11.616 0 006.29 1.84"></path>
            </svg>
            <span class="ml-2">Twitter</span>
          </button>
        </div>
      </div>
    </form>
  </div>
</div>

نمط التسمية العائمة

أنشئ مدخلات تسمية عائمة حديثة:

مدخلات التسمية العائمة

<form class="max-w-md mx-auto p-6 space-y-6">
  <!-- إدخال تسمية عائمة -->
  <div class="relative">
    <input
      type="text"
      id="floating-name"
      class="block px-4 pb-2.5 pt-5 w-full text-sm text-gray-900 bg-white border border-gray-300 rounded-lg appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent peer"
      placeholder=" "
    >
    <label
      for="floating-name"
      class="absolute text-sm text-gray-500 duration-300 transform -translate-y-4 scale-75 top-4 z-10 origin-[0] left-4 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-4 peer-focus:text-blue-600"
    >
      Full Name
    </label>
  </div>

  <!-- بريد إلكتروني بتسمية عائمة -->
  <div class="relative">
    <input
      type="email"
      id="floating-email"
      class="block px-4 pb-2.5 pt-5 w-full text-sm text-gray-900 bg-white border border-gray-300 rounded-lg appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent peer"
      placeholder=" "
    >
    <label
      for="floating-email"
      class="absolute text-sm text-gray-500 duration-300 transform -translate-y-4 scale-75 top-4 z-10 origin-[0] left-4 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-4 peer-focus:text-blue-600"
    >
      Email Address
    </label>
  </div>

  <!-- textarea بتسمية عائمة -->
  <div class="relative">
    <textarea
      id="floating-message"
      rows="4"
      class="block px-4 pb-2.5 pt-5 w-full text-sm text-gray-900 bg-white border border-gray-300 rounded-lg appearance-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent peer resize-none"
      placeholder=" "
    ></textarea>
    <label
      for="floating-message"
      class="absolute text-sm text-gray-500 duration-300 transform -translate-y-4 scale-75 top-4 z-10 origin-[0] left-4 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-4 peer-focus:text-blue-600"
    >
      Message
    </label>
  </div>
</form>
معدل Peer: فئة peer على المدخل ومعدلات peer-* على التسمية تنشئ التأثير العائم. يجب أن يكون placeholder مسافة (" ") لكي تعمل حالة peer-placeholder-shown بشكل صحيح.

مجموعات الإدخال مع الأيقونات

أضف أيقونات وأزرار إلى حقول الإدخال:

مجموعات الإدخال

<form class="max-w-md mx-auto p-6 space-y-4">
  <!-- إدخال مع أيقونة يسارية -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-2">Email</label>
    <div class="relative">
      <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
        <svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"></path>
        </svg>
      </div>
      <input
        type="email"
        class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
        placeholder="you@example.com"
      >
    </div>
  </div>

  <!-- إدخال مع زر يميني -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-2">Website</label>
    <div class="flex rounded-lg shadow-sm">
      <span class="inline-flex items-center px-3 rounded-l-lg border border-r-0 border-gray-300 bg-gray-50 text-gray-500 text-sm">
        https://
      </span>
      <input
        type="text"
        class="flex-1 min-w-0 block w-full px-3 py-2 border border-gray-300 rounded-none focus:ring-blue-500 focus:border-blue-500"
        placeholder="www.example.com"
      >
      <button
        type="button"
        class="inline-flex items-center px-4 rounded-r-lg border border-l-0 border-gray-300 bg-gray-50 text-gray-700 hover:bg-gray-100 text-sm"
      >
        Copy
      </button>
    </div>
  </div>

  <!-- كلمة المرور مع تبديل الرؤية -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-2">Password</label>
    <div class="relative">
      <input
        type="password"
        id="password-toggle"
        class="block w-full px-3 py-2 pr-10 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
        placeholder="Enter password"
      >
      <button
        type="button"
        onclick="togglePassword()"
        class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600"
      >
        <svg id="eye-open" class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
        </svg>
        <svg id="eye-closed" class="h-5 w-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"></path>
        </svg>
      </button>
    </div>
  </div>
</form>

<script>
  function togglePassword() {
    const input = document.getElementById('password-toggle');
    const eyeOpen = document.getElementById('eye-open');
    const eyeClosed = document.getElementById('eye-closed');

    if (input.type === 'password') {
      input.type = 'text';
      eyeOpen.classList.add('hidden');
      eyeClosed.classList.remove('hidden');
    } else {
      input.type = 'password';
      eyeOpen.classList.remove('hidden');
      eyeClosed.classList.add('hidden');
    }
  }
</script>

مكون شريط البحث

ابنِ تصاميم شريط بحث متنوعة:

أشرطة البحث

<!-- بحث بسيط -->
<div class="relative max-w-md">
  <input
    type="search"
    class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
    placeholder="Search..."
  >
  <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
    <svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
    </svg>
  </div>
</div>

<!-- بحث مع زر -->
<div class="flex max-w-md">
  <input
    type="search"
    class="flex-1 px-4 py-2 border border-r-0 border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
    placeholder="Search products..."
  >
  <button class="px-6 bg-blue-600 text-white rounded-r-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
    Search
  </button>
</div>

<!-- بحث مع قائمة منسدلة للتصفية -->
<div class="flex max-w-2xl">
  <select class="px-4 py-2 border border-r-0 border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white">
    <option>All</option>
    <option>Products</option>
    <option>Articles</option>
    <option>Users</option>
  </select>
  <input
    type="search"
    class="flex-1 px-4 py-2 border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"
    placeholder="Type to search..."
  >
  <button class="px-6 bg-blue-600 text-white rounded-r-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
    <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
    </svg>
  </button>
</div>

تراكب نافذة منبثقة حوارية

ابنِ نوافذ منبثقة حوارية يمكن الوصول إليها مع خلفية:

نافذة منبثقة أساسية

<!-- زر تشغيل النافذة المنبثقة -->
<button
  onclick="openModal()"
  class="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
  Open Modal
</button>

<!-- نافذة منبثقة -->
<div
  id="modal"
  class="hidden fixed inset-0 z-50 overflow-y-auto"
  aria-labelledby="modal-title"
  role="dialog"
  aria-modal="true"
>
  <!-- الخلفية -->
  <div class="fixed inset-0 bg-black bg-opacity-50 transition-opacity"></div>

  <!-- حاوية النافذة المنبثقة -->
  <div class="flex min-h-screen items-center justify-center p-4">
    <!-- محتوى النافذة المنبثقة -->
    <div class="relative bg-white rounded-lg shadow-xl max-w-md w-full transform transition-all">
      <!-- زر الإغلاق -->
      <button
        onclick="closeModal()"
        class="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
      >
        <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
        </svg>
      </button>

      <!-- رأس النافذة المنبثقة -->
      <div class="p-6 pb-4">
        <h3 id="modal-title" class="text-2xl font-bold text-gray-900">
          Modal Title
        </h3>
      </div>

      <!-- جسم النافذة المنبثقة -->
      <div class="px-6 pb-6">
        <p class="text-gray-600 mb-4">
          This is a simple modal dialog. You can add any content here like forms, images, or text.
        </p>

        <!-- أزرار الإجراء -->
        <div class="flex gap-3 justify-end">
          <button
            onclick="closeModal()"
            class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50"
          >
            Cancel
          </button>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
            Confirm
          </button>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
  function openModal() {
    document.getElementById('modal').classList.remove('hidden');
    document.body.style.overflow = 'hidden'; // منع تمرير الجسم
  }

  function closeModal() {
    document.getElementById('modal').classList.add('hidden');
    document.body.style.overflow = ''; // استعادة تمرير الجسم
  }

  // إغلاق عند النقر على الخلفية
  document.getElementById('modal').addEventListener('click', function(e) {
    if (e.target === this) {
      closeModal();
    }
  });

  // إغلاق عند مفتاح Escape
  document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') {
      closeModal();
    }
  });
</script>
قفل تمرير الجسم: قم دائماً بتعطيل تمرير الجسم عند فتح نافذة منبثقة (overflow: hidden) واستعده عند الإغلاق. هذا يمنع تمرير الصفحة خلف النافذة المنبثقة.

لوحة انزلاقية

أنشئ لوحات جانبية تنزلق من الحافة:

انزلاقية من اليمين

<button onclick="openSlideOver()" class="px-6 py-3 bg-blue-600 text-white rounded-lg">
  Open Slide-Over
</button>

<!-- لوحة انزلاقية -->
<div id="slide-over" class="hidden fixed inset-0 z-50 overflow-hidden">
  <!-- الخلفية -->
  <div
    onclick="closeSlideOver()"
    class="fixed inset-0 bg-black bg-opacity-50 transition-opacity"
  ></div>

  <!-- حاوية اللوحة -->
  <div class="fixed inset-y-0 right-0 flex max-w-full pl-10">
    <!-- اللوحة -->
    <div class="w-screen max-w-md transform transition-transform">
      <div class="flex h-full flex-col bg-white shadow-xl">
        <!-- الرأس -->
        <div class="px-6 py-6 bg-blue-600">
          <div class="flex items-center justify-between">
            <h2 class="text-xl font-semibold text-white">Panel Title</h2>
            <button onclick="closeSlideOver()" class="text-white hover:text-gray-200">
              <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
              </svg>
            </button>
          </div>
        </div>

        <!-- الجسم -->
        <div class="flex-1 overflow-y-auto px-6 py-6">
          <p class="text-gray-600 mb-4">
            This is a slide-over panel. It slides in from the right side of the screen.
          </p>
          <!-- أضف محتواك هنا -->
        </div>

        <!-- التذييل -->
        <div class="border-t border-gray-200 px-6 py-4">
          <div class="flex gap-3 justify-end">
            <button onclick="closeSlideOver()" class="px-4 py-2 border border-gray-300 rounded-lg">
              Cancel
            </button>
            <button class="px-4 py-2 bg-blue-600 text-white rounded-lg">
              Save
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<script>
  function openSlideOver() {
    const panel = document.getElementById('slide-over');
    panel.classList.remove('hidden');
    // أضف الرسوم المتحركة بعد أن يكون العنصر مرئياً
    setTimeout(() => {
      panel.querySelector('.transform').classList.remove('translate-x-full');
    }, 10);
  }

  function closeSlideOver() {
    const panel = document.getElementById('slide-over');
    panel.querySelector('.transform').classList.add('translate-x-full');
    setTimeout(() => {
      panel.classList.add('hidden');
    }, 300);
  }
</script>

تنقل الدرج

درج بنمط المحمول ينزلق من اليسار:

قائمة درج المحمول

<button onclick="openDrawer()" class="px-4 py-2 bg-gray-800 text-white rounded-lg">
  Open Drawer
</button>

<div id="drawer" class="hidden fixed inset-0 z-50 overflow-hidden">
  <!-- الخلفية -->
  <div
    onclick="closeDrawer()"
    class="fixed inset-0 bg-black bg-opacity-50 transition-opacity"
  ></div>

  <!-- الدرج -->
  <div class="fixed inset-y-0 left-0 max-w-xs w-full bg-white shadow-xl transform -translate-x-full transition-transform duration-300" id="drawer-content">
    <!-- الرأس -->
    <div class="flex items-center justify-between p-6 border-b">
      <h2 class="text-xl font-bold text-gray-900">Menu</h2>
      <button onclick="closeDrawer()" class="text-gray-400 hover:text-gray-600">
        <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
        </svg>
      </button>
    </div>

    <!-- التنقل -->
    <nav class="p-6 space-y-2">
      <a href="#" class="block px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100">Home</a>
      <a href="#" class="block px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100">About</a>
      <a href="#" class="block px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100">Services</a>
      <a href="#" class="block px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100">Contact</a>
    </nav>
  </div>
</div>

<script>
  function openDrawer() {
    document.getElementById('drawer').classList.remove('hidden');
    setTimeout(() => {
      document.getElementById('drawer-content').classList.remove('-translate-x-full');
    }, 10);
  }

  function closeDrawer() {
    document.getElementById('drawer-content').classList.add('-translate-x-full');
    setTimeout(() => {
      document.getElementById('drawer').classList.add('hidden');
    }, 300);
  }
</script>

نافذة منبثقة مع ضبابية الخلفية

أنشئ نوافذ منبثقة حديثة مع خلفيات ضبابية:

نافذة منبثقة بضبابية الخلفية

<button onclick="openBlurModal()" class="px-6 py-3 bg-purple-600 text-white rounded-lg">
  Open Blur Modal
</button>

<div id="blur-modal" class="hidden fixed inset-0 z-50">
  <!-- خلفية ضبابية -->
  <div class="fixed inset-0 bg-black/30 backdrop-blur-sm"></div>

  <!-- نافذة منبثقة -->
  <div class="flex min-h-screen items-center justify-center p-4">
    <div class="relative bg-white/90 backdrop-blur-md rounded-2xl shadow-2xl max-w-lg w-full p-8">
      <button
        onclick="closeBlurModal()"
        class="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
      >
        <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
        </svg>
      </button>

      <h3 class="text-2xl font-bold text-gray-900 mb-4">
        Glassmorphism Modal
      </h3>

      <p class="text-gray-600 mb-6">
        This modal uses backdrop-blur for a modern glassmorphism effect. The background is slightly blurred and semi-transparent.
      </p>

      <div class="flex gap-3 justify-end">
        <button onclick="closeBlurModal()" class="px-4 py-2 border border-gray-300 rounded-lg">
          Cancel
        </button>
        <button class="px-4 py-2 bg-purple-600 text-white rounded-lg">
          Continue
        </button>
      </div>
    </div>
  </div>
</div>

<script>
  function openBlurModal() {
    document.getElementById('blur-modal').classList.remove('hidden');
  }

  function closeBlurModal() {
    document.getElementById('blur-modal').classList.add('hidden');
  }
</script>
ضبابية الخلفية: تنشئ أداة backdrop-blur-sm تأثير ضبابية على العناصر خلف النافذة المنبثقة. اجمع مع خلفيات شبه شفافة (bg-black/30) لتأثيرات glassmorphism.

تمرين 1: نموذج التسجيل

ابنِ نموذج تسجيل متعدد الخطوات كامل:

  • الخطوة 1: البريد الإلكتروني وكلمة المرور مع التحقق
  • الخطوة 2: الاسم، الهاتف، تاريخ الميلاد
  • الخطوة 3: العنوان والتفضيلات
  • مؤشر تقدم يوضح الخطوة الحالية
  • أزرار التالي/السابق/الإرسال مع الحالات المناسبة
  • أخطاء التحقق لكل حقل

تمرين 2: نافذة تأكيد منبثقة

أنشئ مكون نافذة تأكيد منبثقة قابلة لإعادة الاستخدام:

  • أيقونة تحذير مع متغيرات مختلفة (معلومات، تحذير، خطر، نجاح)
  • خصائص العنوان والوصف
  • أزرار إلغاء وتأكيد مع نص وألوان قابلة للتخصيص
  • النقر على الخلفية ومفتاح Escape للإغلاق
  • رسوم متحركة سلسة للظهور/الاختفاء
  • مصيدة التركيز (التنقل بلوحة المفاتيح يبقى داخل النافذة المنبثقة)

تمرين 3: لوحة سلة التسوق الانزلاقية

ابنِ لوحة سلة تسوق تنزلق من اليمين:

  • قائمة بعناصر السلة مع صورة، اسم، سعر، عناصر التحكم في الكمية
  • زر إزالة العنصر لكل منتج
  • حساب الإجمالي الفرعي، الضريبة، والإجمالي
  • زر الدفع في التذييل
  • حالة السلة الفارغة مع توضيح
  • رسوم متحركة انزلاق سلسة من الحافة اليمنى