إطار Tailwind CSS

الإضافات: الرسمية والمخصصة

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

الإضافات: الرسمية والمخصصة

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

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

إضافات Tailwind الرسمية

يحافظ Tailwind على العديد من الإضافات الرسمية التي تضيف وظائف متخصصة. دعنا نستكشف كل واحدة:

1. @tailwindcss/typography (إضافة Prose)

توفر إضافة typography أنماطًا افتراضية جميلة للمحتوى الذي لا تتحكم فيه، مثل markdown أو محتوى CMS:

تثبيت إضافة Typography

# تثبيت الإضافة
npm install @tailwindcss/typography

# أو مع yarn
yarn add @tailwindcss/typography

التكوين في tailwind.config.js

// tailwind.config.js
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('@tailwindcss/typography'),
  ],
}

الآن يمكنك استخدام فئة prose على أي حاوية تحتوي على محتوى من إنشاء المستخدم:

استخدام فئة Prose

<article class="prose lg:prose-xl">
  <h1>عنوان المقال</h1>
  <p>هذه فقرة مع <a href="#">رابط</a> و <strong>نص عريض</strong>.</p>
  <h2>عنوان فرعي</h2>
  <p>المزيد من المحتوى هنا...</p>
  <ul>
    <li>عنصر القائمة 1</li>
    <li>عنصر القائمة 2</li>
  </ul>
  <blockquote>
    اقتباس جميل مع تصميم مناسب
  </blockquote>
</article>

<!-- مع دعم الوضع الداكن -->
<article class="prose dark:prose-invert lg:prose-xl">
  <!-- المحتوى مصمم تلقائيًا للوضع الداكن -->
</article>

<!-- سمات ألوان مختلفة -->
<article class="prose prose-slate"><!-- سمة Slate --></article>
<article class="prose prose-gray"><!-- سمة Gray --></article>
<article class="prose prose-zinc"><!-- سمة Zinc --></article>
<article class="prose prose-stone"><!-- سمة Stone --></article>

<!-- معدّلات الحجم -->
<article class="prose prose-sm"><!-- صغير --></article>
<article class="prose prose-base"><!-- افتراضي --></article>
<article class="prose prose-lg"><!-- كبير --></article>
<article class="prose prose-xl"><!-- كبير جدًا --></article>
<article class="prose prose-2xl"><!-- 2X كبير --></article>
تخصيص Prose: يمكنك تخصيص أنماط prose في إعداداتك:
module.exports = {
  theme: {
    extend: {
      typography: {
        DEFAULT: {
          css: {
            color: '#333',
            a: {
              color: '#3182ce',
              '&:hover': {
                color: '#2c5282',
              },
            },
          },
        },
      },
    },
  },
}

2. @tailwindcss/forms

توفر إضافة forms أنماطًا افتراضية جميلة لعناصر النماذج:

تثبيت إضافة Forms

# التثبيت
npm install @tailwindcss/forms

# التكوين
// tailwind.config.js
module.exports = {
  plugins: [
    require('@tailwindcss/forms'),
  ],
}

مع تثبيت الإضافة، تحصل جميع عناصر النماذج على أنماط افتراضية جميلة:

عناصر النموذج المصممة

<form class="space-y-4">
  <!-- إدخال نص - مصمم تلقائيًا -->
  <input type="text" placeholder="عنوان البريد الإلكتروني" />

  <!-- منطقة نص - مصممة تلقائيًا -->
  <textarea rows="4" placeholder="رسالتك"></textarea>

  <!-- قائمة منسدلة - مصممة تلقائيًا -->
  <select>
    <option>الخيار 1</option>
    <option>الخيار 2</option>
  </select>

  <!-- خانة اختيار - مصممة تلقائيًا -->
  <input type="checkbox" />

  <!-- زر اختيار - مصمم تلقائيًا -->
  <input type="radio" name="option" />

  <!-- إدخال ملف - مصمم تلقائيًا -->
  <input type="file" />
</form>

<!-- التجاوز بفئات الأدوات -->
<input type="text" class="rounded-full border-purple-500" />

3. @tailwindcss/aspect-ratio

تساعدك إضافة aspect-ratio في الحفاظ على نسب العرض إلى الارتفاع للعناصر المتجاوبة:

تثبيت إضافة Aspect Ratio

# التثبيت
npm install @tailwindcss/aspect-ratio

# التكوين
module.exports = {
  plugins: [
    require('@tailwindcss/aspect-ratio'),
  ],
}

استخدام نسب العرض إلى الارتفاع

<!-- تضمين فيديو بنسبة 16:9 -->
<div class="aspect-w-16 aspect-h-9">
  <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"
          class="w-full h-full"></iframe>
</div>

<!-- مربع (1:1) -->
<div class="aspect-w-1 aspect-h-1">
  <img src="profile.jpg" class="object-cover" />
</div>

<!-- نسبة العرض إلى الارتفاع 4:3 -->
<div class="aspect-w-4 aspect-h-3">
  <img src="photo.jpg" class="object-cover" />
</div>

<!-- 21:9 عريض جدًا -->
<div class="aspect-w-21 aspect-h-9">
  <video src="video.mp4" class="object-cover"></video>
</div>
بديل CSS الحديث: تدعم المتصفحات الحديثة الآن aspect-ratio CSS الأصلي. يمكنك استخدام aspect-square، aspect-video، أو قيم اعتباطية مثل aspect-[4/3] في Tailwind بدون الإضافة.

4. @tailwindcss/container-queries

تسمح استعلامات الحاوية بتصميم العناصر بناءً على حجم حاويتها، وليس حجم منفذ العرض:

تثبيت إضافة Container Queries

# التثبيت
npm install @tailwindcss/container-queries

# التكوين
module.exports = {
  plugins: [
    require('@tailwindcss/container-queries'),
  ],
}

استخدام استعلامات الحاوية

<!-- اجعل الأب حاوية -->
<div class="@container">
  <!-- صمّم الابن بناءً على عرض الحاوية، وليس منفذ العرض -->
  <div class="@sm:text-lg @md:text-xl @lg:text-2xl">
    حجم هذا النص يستجيب لعرض الحاوية
  </div>
</div>

<!-- حاويات مسماة -->
<div class="@container/sidebar">
  <div class="@lg/sidebar:flex-row flex-col">
    التخطيط يتغير بناءً على حاوية الشريط الجانبي
  </div>
</div>

<!-- مثال بطاقة عملي -->
<div class="@container">
  <div class="flex @md:flex-row flex-col gap-4">
    <img src="image.jpg" class="@md:w-48 w-full" />
    <div class="flex-1">
      <h3 class="@md:text-xl text-lg">عنوان البطاقة</h3>
      <p class="@sm:block hidden">الوصف مرئي في الحاويات الأكبر</p>
    </div>
  </div>
</div>

إنشاء إضافات مخصصة

تتيح لك الإضافات المخصصة توسيع Tailwind بأدواتك ومكوناتك ومتغيراتك الخاصة. هناك عدة طرق لواجهة برمجة الإضافات:

طرق واجهة برمجة الإضافات

  • addUtilities(): إضافة فئات أدوات جديدة
  • addComponents(): إضافة فئات مكونات جديدة
  • addBase(): إضافة أنماط أساسية (مثل normalize.css)
  • matchUtilities(): إضافة أدوات تدعم القيم الاعتباطية
  • addVariant(): إضافة متغيرات مخصصة (مثل hover:، focus:)

1. إضافة أدوات بسيطة

إضافة مخصصة أساسية

// tailwind.config.js
const plugin = require('tailwindcss/plugin');

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      const newUtilities = {
        '.text-shadow': {
          textShadow: '2px 2px 4px rgba(0, 0, 0, 0.1)',
        },
        '.text-shadow-md': {
          textShadow: '4px 4px 8px rgba(0, 0, 0, 0.15)',
        },
        '.text-shadow-lg': {
          textShadow: '6px 6px 12px rgba(0, 0, 0, 0.2)',
        },
        '.text-shadow-none': {
          textShadow: 'none',
        },
      };

      addUtilities(newUtilities);
    }),
  ],
};

// الاستخدام في HTML
<h1 class="text-shadow-md">نص مع ظل</h1>

2. إضافة أدوات مع المتغيرات

إضافة مع دعم متجاوب و Hover

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.rotate-y-180': {
          transform: 'rotateY(180deg)',
        },
        '.rotate-x-180': {
          transform: 'rotateX(180deg)',
        },
        '.preserve-3d': {
          transformStyle: 'preserve-3d',
        },
        '.perspective-1000': {
          perspective: '1000px',
        },
        '.backface-hidden': {
          backfaceVisibility: 'hidden',
        },
      });
    }),
  ],
};

// الاستخدام مع المتغيرات
<div class="hover:rotate-y-180 transition-transform duration-500
            preserve-3d backface-hidden">
  قلب البطاقة عند التحويم
</div>

3. إضافة مكونات

إضافة المكونات

module.exports = {
  plugins: [
    plugin(function({ addComponents, theme }) {
      const buttons = {
        '.btn': {
          padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
          borderRadius: theme('borderRadius.md'),
          fontWeight: theme('fontWeight.semibold'),
          transition: 'all 0.2s',
          '&:focus': {
            outline: 'none',
            boxShadow: theme('boxShadow.md'),
          },
        },
        '.btn-primary': {
          backgroundColor: theme('colors.blue.500'),
          color: theme('colors.white'),
          '&:hover': {
            backgroundColor: theme('colors.blue.600'),
          },
        },
        '.btn-secondary': {
          backgroundColor: theme('colors.gray.200'),
          color: theme('colors.gray.800'),
          '&:hover': {
            backgroundColor: theme('colors.gray.300'),
          },
        },
      };

      addComponents(buttons);
    }),
  ],
};

// الاستخدام
<button class="btn btn-primary">أساسي</button>
<button class="btn btn-secondary">ثانوي</button>

4. إضافة أنماط أساسية

إضافة الأنماط الأساسية

module.exports = {
  plugins: [
    plugin(function({ addBase, theme }) {
      addBase({
        'h1': {
          fontSize: theme('fontSize.4xl'),
          fontWeight: theme('fontWeight.bold'),
          marginBottom: theme('spacing.4'),
        },
        'h2': {
          fontSize: theme('fontSize.3xl'),
          fontWeight: theme('fontWeight.semibold'),
          marginBottom: theme('spacing.3'),
        },
        'a': {
          color: theme('colors.blue.600'),
          textDecoration: 'underline',
          '&:hover': {
            color: theme('colors.blue.800'),
          },
        },
        'code': {
          backgroundColor: theme('colors.gray.100'),
          padding: `${theme('spacing.1')} ${theme('spacing.2')}`,
          borderRadius: theme('borderRadius.md'),
          fontSize: theme('fontSize.sm'),
        },
      });
    }),
  ],
};

5. Match Utilities (القيم الاعتباطية)

هذا هو نوع الإضافة الأقوى—ينشئ أدوات تدعم القيم الاعتباطية:

إضافة Match Utilities

const plugin = require('tailwindcss/plugin');

module.exports = {
  plugins: [
    plugin(function({ matchUtilities, theme }) {
      // إنشاء أداة 'text-shadow-[value]'
      matchUtilities(
        {
          'text-shadow': (value) => ({
            textShadow: value,
          }),
        },
        { values: theme('textShadow') }
      );

      // إنشاء أداة 'grid-cols-auto-[value]'
      matchUtilities(
        {
          'grid-cols-auto': (value) => ({
            gridTemplateColumns: `repeat(auto-fit, minmax(${value}, 1fr))`,
          }),
        }
      );
    }),
  ],

  theme: {
    extend: {
      textShadow: {
        sm: '1px 1px 2px rgba(0, 0, 0, 0.1)',
        DEFAULT: '2px 2px 4px rgba(0, 0, 0, 0.15)',
        lg: '4px 4px 8px rgba(0, 0, 0, 0.2)',
      },
    },
  },
};

// الاستخدام
<h1 class="text-shadow">ظل افتراضي</h1>
<h1 class="text-shadow-lg">ظل كبير</h1>
<h1 class="text-shadow-[3px_3px_6px_rgba(0,0,0,0.3)]">ظل اعتباطي</h1>

<div class="grid grid-cols-auto-[250px]">
  شبكة Auto-fit بحد أدنى 250px
</div>

6. المتغيرات المخصصة

إضافة متغيرات مخصصة

module.exports = {
  plugins: [
    plugin(function({ addVariant }) {
      // إضافة متغير 'hocus' (hover أو focus)
      addVariant('hocus', ['&:hover', '&:focus']);

      // إضافة متغير 'not-first'
      addVariant('not-first', '&:not(:first-child)');

      // إضافة متغير 'not-last'
      addVariant('not-last', '&:not(:last-child)');

      // إضافة متغير 'optional' (لحقول النماذج الاختيارية)
      addVariant('optional', '&:optional');

      // إضافة متغير 'group-focus-within'
      addVariant('group-focus-within', ':merge(.group):focus-within &');

      // إضافة متغير الأطفال
      addVariant('children', '& > *');
    }),
  ],
};

// الاستخدام
<button class="hocus:bg-blue-600">التحويم أو التركيز</button>
<li class="not-first:border-t">عنصر قائمة مع حد علوي (باستثناء الأول)</li>
<input class="optional:border-gray-300">حقل اختياري</input>
<div class="group">
  <input />
  <div class="group-focus-within:visible invisible">نص المساعدة</div>
</div>

مثال إضافة من العالم الحقيقي

دعنا ننشئ إضافة شاملة بميزات متعددة:

إضافة مخصصة كاملة

// tailwind.config.js
const plugin = require('tailwindcss/plugin');

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, addBase, matchUtilities, theme, addVariant }) {

      // 1. إضافة أنماط أساسية
      addBase({
        '::selection': {
          backgroundColor: theme('colors.blue.200'),
          color: theme('colors.blue.900'),
        },
      });

      // 2. إضافة أدوات مخصصة
      addUtilities({
        '.scrollbar-hide': {
          '-ms-overflow-style': 'none',
          'scrollbar-width': 'none',
          '&::-webkit-scrollbar': {
            display: 'none',
          },
        },
        '.scrollbar-default': {
          '-ms-overflow-style': 'auto',
          'scrollbar-width': 'auto',
          '&::-webkit-scrollbar': {
            display: 'block',
          },
        },
      });

      // 3. إضافة مكونات
      addComponents({
        '.card': {
          backgroundColor: theme('colors.white'),
          borderRadius: theme('borderRadius.lg'),
          padding: theme('spacing.6'),
          boxShadow: theme('boxShadow.lg'),
        },
        '.badge': {
          display: 'inline-flex',
          alignItems: 'center',
          padding: `${theme('spacing.1')} ${theme('spacing.2')}`,
          borderRadius: theme('borderRadius.full'),
          fontSize: theme('fontSize.xs'),
          fontWeight: theme('fontWeight.medium'),
        },
      });

      // 4. إضافة matchUtilities للقيم الاعتباطية
      matchUtilities(
        {
          'animate-delay': (value) => ({
            animationDelay: value,
          }),
        },
        { values: theme('transitionDelay') }
      );

      // 5. إضافة متغيرات مخصصة
      addVariant('not-last', '&:not(:last-child)');
      addVariant('hocus', ['&:hover', '&:focus']);
    }),
  ],

  theme: {
    extend: {
      transitionDelay: {
        '100': '100ms',
        '200': '200ms',
        '300': '300ms',
      },
    },
  },
};

خيارات الإضافة

يمكنك إنشاء إضافات قابلة للتكوين تقبل الخيارات:

إضافة مع خيارات

// custom-plugin.js
const plugin = require('tailwindcss/plugin');

module.exports = plugin.withOptions(
  function (options = {}) {
    return function ({ addUtilities }) {
      const { prefix = 'custom' } = options;

      addUtilities({
        [`.${prefix}-utility`]: {
          // أنماطك
        },
      });
    };
  },
  function (options = {}) {
    return {
      theme: {
        extend: {
          // امتدادات السمة بناءً على الخيارات
        },
      },
    };
  }
);

// الاستخدام في tailwind.config.js
module.exports = {
  plugins: [
    require('./custom-plugin')({ prefix: 'my' }),
  ],
};

تمرين تطبيقي

المهمة: أنشئ إضافة مخصصة للأنماط الشائعة:

  1. أضف فئة مكون .glass لتأثير glassmorphism (backdrop blur، خلفية شبه شفافة، حدود)
  2. أنشئ أداة .gradient-text لنص تدريجي مع webkit background clip
  3. أضف matchUtilities .text-outline-[width] لضربة النص
  4. أنشئ متغير group-open مخصص لعناصر details/summary
  5. أضف أدوات .animate-slide-in-[direction] (أعلى، أسفل، يسار، يمين)
  6. اختبر جميع الأدوات مع المتغيرات المتجاوبة والوضع الداكن

تمرين التحدي

المهمة المتقدمة: ابنِ نظام إضافة أدوات كامل:

  1. أنشئ إضافة تضيف أدوات تصميم شريط التمرير (العرض، اللون، المسار، الإبهام)
  2. أضف أدوات تصميم نص التحديد (الخلفية، اللون، text-decoration)
  3. أنشئ أدوات رسوم متحركة متقدمة: pause، play-state، fill-mode، iteration-count
  4. أضف أدوات المرشح لمرشحات SVG (blur، brightness، contrast، drop-shadow)
  5. أنشئ أدوات أشكال هندسية باستخدام clip-path (دائرة، مثلث، سداسي، سهم)
  6. أضف أدوات الشبكة المخصصة: auto-fit، auto-fill مع قيم min/max اعتباطية
  7. أنشئ مكون .debug يضيف خطوط محيطة لجميع الأطفال (لتصحيح التخطيط)
  8. اجعل جميع الأدوات تعمل مع القيم الاعتباطية، المتغيرات المتجاوبة، والوضع الداكن
  9. قم بالتعبئة كإضافة npm قابلة لإعادة الاستخدام مع الوثائق
نصيحة احترافية: قبل إنشاء إضافة مخصصة، تحقق مما إذا كانت الوظيفة موجودة بالفعل في Tailwind الأساسي أو يمكن تحقيقها بقيم اعتباطية. أنشئ إضافات فقط للأدوات التي تستخدمها بشكل متكرر أو التي تحتاج إلى منطق خاص.

الملخص

في هذا الدرس، تعلمت:

  • إضافات Tailwind الرسمية: typography، forms، aspect-ratio، container-queries
  • كيفية تثبيت وتكوين الإضافات
  • طرق واجهة برمجة الإضافات: addUtilities، addComponents، addBase، matchUtilities، addVariant
  • إنشاء إضافات أدوات بسيطة
  • بناء إضافات مكونات تستخدم قيم السمة
  • إضافة أنماط أساسية لعناصر HTML
  • إنشاء match utilities التي تدعم القيم الاعتباطية
  • إضافة متغيرات مخصصة للمحددات الخاصة
  • بناء إضافات قابلة للتكوين مع الخيارات
  • أفضل الممارسات لتطوير الإضافات

الإضافات هي المفتاح لجعل Tailwind ملكك حقًا. سواء كنت تستخدم الإضافات الرسمية للأنماط الشائعة أو تنشئ إضافات مخصصة للاحتياجات الخاصة بالمشروع، لديك الآن الأدوات لتوسيع Tailwind بشكل لا نهائي. تهانينا على إكمال هذه الدورة الشاملة لـ Tailwind CSS!