اگر می‌خواهید کاربران سایت بتوانند در هر صفحه به سرعت به شبکه های اجتماعی، پیام رسان‌ها، شماره تماس یا ایمیل شما دسترسی داشته باشند، استفاده از یک منوی شناور ارتباطی می‌تواند راهکار ساده و کاربردی باشد.

در این مطلب یک کد آماده برای ایجاد منوی شناور در وردپرس معرفی می‌کنیم که بدون نیاز به نصب یک افزونه اختصاصی برای این قابلیت، امکان نمایش لینک شبکه‌های اجتماعی و راه‌های ارتباطی مختلف را در اختیار شما قرار می‌دهد.

این منو می‌تواند در کنار محتوای سایت قرار بگیرد و کاربر با کلیک روی دکمه اصلی، فهرست سرویس‌های ارتباطی را مشاهده کند.

منوی شناور شبکه‌های اجتماعی در وردپرس چیست؟

منوی شناور شبکه‌های اجتماعی بخشی از رابط کاربری سایت است که معمولاً در یکی از گوشه‌های صفحه قرار می‌گیرد و با کلیک روی آیکون اصلی، گزینه‌های مختلف ارتباطی را نمایش می‌دهد.

به‌جای اینکه لینک شبکه‌های اجتماعی را فقط در فوتر یا صفحه تماس با ما قرار دهید، می‌توانید آن‌ها را همیشه در دسترس کاربر قرار دهید.

این روش به‌خصوص برای سایت‌هایی که از چند پیام‌رسان یا شبکه اجتماعی استفاده می‌کنند، کاربرد زیادی دارد.

این منوی شناور چه امکاناتی دارد؟

کدی که در این مطلب ارائه شده، برای نمایش مجموعه‌ای از راه‌های ارتباطی طراحی شده و می‌تواند شامل سرویس‌های زیر باشد:

  • آپارات
  • بله
  • ایتا
  • گپ
  • آی‌گپ
  • اینستاگرام
  • روبیکا
  • سروش
  • تلگرام
  • واتساپ
  • یوتیوب
  • ایمیل
  • تماس تلفنی

هر گزینه دارای آیکون اختصاصی خود است و کاربر می‌تواند با انتخاب آن، مستقیماً وارد لینک مربوط به همان سرویس شود.

چرا از منوی شناور استفاده کنیم؟

یکی از مهم ترین مزایای این روش، دسترسی سریع تر کاربر به راه های ارتباطی است.

فرض کنید کاربری در حال مطالعه یک مقاله است و قصد دارد از طریق تلگرام یا واتساپ با شما ارتباط برقرار کند. اگر لینک این سرویس‌ها فقط در فوتر سایت قرار گرفته باشد، کاربر باید صفحه را تا انتها اسکرول کند.

اما در منوی شناور، گزینه ارتباطی همیشه در دسترس است.

مهم ترین مزایا

  • دسترسی سریع به شبکه‌های اجتماعی
  • نمایش هم‌زمان چند پیام‌رسان
  • دسترسی سریع به شماره تماس
  • دسترسی مستقیم به ایمیل
  • طراحی مناسب برای سایت‌های فارسی و RTL
  • کاهش نیاز به افزونه‌های متعدد
  • امکان شخصی‌سازی لینک‌ها
  • استفاده از SVG برای آیکون‌ها
  • نمایش آیکون اختصاصی برای هر سرویس
  • امکان استفاده در صفحات مختلف سایت

طراحی آیکون‌ها و حالت Hover

یکی از بخش‌های مهم این منو، طراحی آیکون هاست.

برای هر شبکه اجتماعی از آیکون SVG اختصاصی استفاده شده تا آیکون‌ها بدون نیاز به بارگذاری فایل تصویری جداگانه نمایش داده شوند.

همچنین برای هر سرویس، رنگ متفاوتی در حالت Hover در نظر گرفته شده است.

برای مثال، هنگام قرار گرفتن نشانگر ماوس روی گزینه اینستاگرام، رنگ زمینه آن می‌تواند با رنگ سایر گزینه‌ها متفاوت باشد.

این موضوع باعث می‌شود کاربر بتواند سرویس موردنظر خود را سریع تر تشخیص دهد و ظاهر منو نیز از حالت یکنواخت خارج شود.

چرا استفاده از SVG برای آیکون‌ها مناسب است؟

SVG یک فرمت برداری است و برای نمایش آیکون های رابط کاربری گزینه مناسبی محسوب می‌شود.

در این منو به جای استفاده از تصاویر PNG یا JPG، مسیرهای SVG مستقیماً داخل ساختار کد قرار گرفته‌اند.

در نتیجه آیکون‌ها در اندازه‌های مختلف کیفیت خود را حفظ می‌کنند و نیازی به درخواست HTTP جداگانه برای هر فایل تصویر وجود ندارد.

منوی شناور برای موبایل

یکی از نکات مهم در طراحی چنین منویی، توجه به نمایش آن در موبایل است.

درصد قابل توجهی از کاربران سایت‌ها با گوشی موبایل وارد صفحات می‌شوند؛ بنابراین منوی شناور باید فضای زیادی از صفحه را اشغال نکند و دسترسی به محتوای اصلی را مختل نکند.

در کد ارائه‌شده، ساختار منو به شکلی طراحی شده که بتوان آن را برای نمایشگرهای مختلف تنظیم کرد.

به همین دلیل قبل از استفاده در سایت اصلی، بهتر است منو را در موبایل، تبلت و دسکتاپ بررسی کنید.

آیا برای استفاده از این کد به افزونه جداگانه نیاز داریم؟

این کد به صورت یک قطعه کد قابل استفاده در وردپرس آماده شده است و هدف آن این است که قابلیت منوی شناور را بدون وابستگی به یک افزونه اختصاصی در اختیار شما قرار دهد.

اگر از افزونه‌هایی مانند Code Snippets برای مدیریت قطعه‌کدهای وردپرس استفاده می‌کنید، می‌توانید کد را از طریق همان روش مدیریت کنید.

البته قبل از قرار دادن هر کد سفارشی در سایت اصلی، بهتر است از سایت و تنظیمات فعلی خود نسخه پشتیبان تهیه کنید.

کد شبکه های اجتماعی شناور و نحوه نصب

افزونه Code Snippets اگر نصب ندارید حتما نصب کنید و افزودن را انتخاب کنید، یک عنوان قرار دهید و کد زیر را اضافه کنید و ذخیره و فعالسازی را کلیک کنید .

declare(strict_types=1);

final class Icodito_Floating_Contact_Menu
{

    private const OPTION_NAME = 'icodito_floating_contact_menu';
    private const PAGE_SLUG = 'icodito-floating-contact-menu';
    private const VERSION = '2.3.0';

    private array $defaults = array();

    private array $services = array(
        'igap' => 'آی گپ',
        'bale' => 'بله',
        'soroush' => 'سروش',
        'gap' => 'گپ',
        'eitaa' => 'ایتا',
        'rubika' => 'روبیکا',
        'telegram' => 'تلگرام',
        'whatsapp' => 'واتساپ',
        'instagram' => 'اینستاگرام',
        'aparat' => 'آپارات',
        'youtube' => 'یوتیوب',
        'email' => 'ایمیل',
        'phone' => 'شماره تماس',
    );

    private static ?self $instance = null;

    private function __construct()
    {

        $this->defaults = array(
            'title' => 'راه‌های ارتباطی با ما',
            'button_color' => '#00bcd4',
            'text_color' => '#ffffff',
            'item_background' => '#ffffff',
            'border_radius' => 14,
            'icon_size' => 21,
            'button_size' => 58,
            'bottom_spacing' => 24,
            'side_spacing' => 24,
            'animation_enabled' => 1,
            'animation_speed' => 0.3,
            'position' => 'right',
            'services' => array(),
        );

        $this->defaults['services'] = $this->get_default_services();

        add_action(
            'admin_menu',
            array($this, 'add_admin_menu')
        );

        add_action(
            'admin_init',
            array($this, 'register_settings')
        );

        add_action(
            'admin_enqueue_scripts',
            array($this, 'admin_enqueue_scripts')
        );

        add_action(
            'wp_enqueue_scripts',
            array($this, 'enqueue_frontend_assets')
        );

        add_action(
            'wp_footer',
            array($this, 'render_frontend'),
            99
        );
    }

    public static function instance(): self
    {

        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    private function get_default_services(): array
    {

        $defaults = array();

        foreach ($this->services as $key => $label) {
            $defaults[$key] = array(
                'name' => $label,
                'link' => '',
                'description' => '',
            );
        }

        return $defaults;
    }

    private function get_settings(): array
    {

        $saved = get_option(
            self::OPTION_NAME,
            array()
        );

        if (!is_array($saved)) {
            $saved = array();
        }

        $settings = wp_parse_args(
            $saved,
            $this->defaults
        );

        if (
            !isset($settings['services']) ||
            !is_array($settings['services'])
        ) {
            $settings['services'] = $this->defaults['services'];
        }

        foreach ($this->services as $key => $label) {

            if (
                !isset($settings['services'][$key]) ||
                !is_array($settings['services'][$key])
            ) {
                $settings['services'][$key] = $this->defaults['services'][$key];
            }

            $settings['services'][$key] = wp_parse_args(
                $settings['services'][$key],
                $this->defaults['services'][$key]
            );
        }

        return $settings;
    }

    public function add_admin_menu(): void
    {

        add_options_page(
            'منوی شناور ارتباط',
            'منوی شناور ارتباط',
            'manage_options',
            self::PAGE_SLUG,
            array($this, 'render_settings_page')
        );
    }

    public function register_settings(): void
    {

        register_setting(
            self::PAGE_SLUG,
            self::OPTION_NAME,
            array(
                'type' => 'array',
                'sanitize_callback' => array($this, 'sanitize_settings'),
                'default' => $this->defaults,
            )
        );

        add_settings_section(
            'icodito_fcm_general',
            'تنظیمات عمومی',
            array($this, 'render_general_section'),
            self::PAGE_SLUG
        );

        add_settings_field(
            'title',
            'عنوان بالای دکمه',
            array($this, 'render_title_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general'
        );

        add_settings_field(
            'button_color',
            'رنگ دکمه شناور',
            array($this, 'render_color_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'button_color',
            )
        );

        add_settings_field(
            'text_color',
            'رنگ متن',
            array($this, 'render_color_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'text_color',
            )
        );

        add_settings_field(
            'item_background',
            'رنگ پس‌زمینه آیتم‌ها',
            array($this, 'render_color_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'item_background',
            )
        );


        add_settings_field(
            'border_radius',
            'گردی گوشه کارت‌ها',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'border_radius',
                'min' => 0,
                'max' => 50,
                'step' => 1,
                'suffix' => 'px',
            )
        );

        add_settings_field(
            'icon_size',
            'اندازه آیکون سرویس‌ها',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'icon_size',
                'min' => 12,
                'max' => 64,
                'step' => 1,
                'suffix' => 'px',
            )
        );

        add_settings_field(
            'button_size',
            'اندازه دکمه شناور',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'button_size',
                'min' => 40,
                'max' => 100,
                'step' => 1,
                'suffix' => 'px',
            )
        );

        add_settings_field(
            'bottom_spacing',
            'فاصله از پایین',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'bottom_spacing',
                'min' => 0,
                'max' => 200,
                'step' => 1,
                'suffix' => 'px',
            )
        );

        add_settings_field(
            'side_spacing',
            'فاصله از چپ یا راست',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'side_spacing',
                'min' => 0,
                'max' => 200,
                'step' => 1,
                'suffix' => 'px',
            )
        );

        add_settings_field(
            'animation_enabled',
            'انیمیشن',
            array($this, 'render_animation_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general'
        );

        add_settings_field(
            'animation_speed',
            'سرعت انیمیشن',
            array($this, 'render_number_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general',
            array(
                'key' => 'animation_speed',
                'min' => 0.05,
                'max' => 2,
                'step' => 0.05,
                'suffix' => 'ثانیه',
            )
        );

        add_settings_field(
            'position',
            'سمت نمایش',
            array($this, 'render_position_field'),
            self::PAGE_SLUG,
            'icodito_fcm_general'
        );

        add_settings_section(
            'icodito_fcm_services',
            'لیست سرویس‌ها',
            array($this, 'render_services_section'),
            self::PAGE_SLUG
        );

        foreach ($this->services as $key => $label) {

            add_settings_field(
                'service_' . $key,
                $label,
                array($this, 'render_service_field'),
                self::PAGE_SLUG,
                'icodito_fcm_services',
                array(
                    'key' => $key,
                    'label' => $label,
                )
            );
        }

        add_settings_section(
            'icodito_fcm_guide',
            'راهنمای وارد کردن لینک‌ها',
            array($this, 'render_guide_section'),
            self::PAGE_SLUG
        );
    }

    public function sanitize_settings($input): array
    {

        $old_settings = $this->get_settings();

        if (!is_array($input)) {
            return $old_settings;
        }

        $output = $old_settings;

        if (isset($input['title'])) {

            $output['title'] = sanitize_text_field(
                wp_unslash(
                    (string) $input['title']
                )
            );
        }

        $color_fields = array(
            'button_color',
            'text_color',
            'item_background',
        );

        foreach ($color_fields as $field) {

            if (!isset($input[$field])) {
                continue;
            }

            $color = sanitize_hex_color(
                wp_unslash(
                    (string) $input[$field]
                )
            );

            if (null !== $color) {
                $output[$field] = $color;
            }
        }

        $integer_fields = array(
            'border_radius',
            'icon_size',
            'button_size',
            'bottom_spacing',
            'side_spacing',
        );

        foreach ($integer_fields as $field) {

            if (
                isset($input[$field]) &&
                is_numeric($input[$field])
            ) {
                $output[$field] = absint(
                    $input[$field]
                );
            }
        }

        $output['border_radius'] = min(
            50,
            max(
                0,
                (int) $output['border_radius']
            )
        );

        $output['icon_size'] = min(
            64,
            max(
                12,
                (int) $output['icon_size']
            )
        );

        $output['button_size'] = min(
            100,
            max(
                40,
                (int) $output['button_size']
            )
        );

        $output['bottom_spacing'] = min(
            200,
            max(
                0,
                (int) $output['bottom_spacing']
            )
        );

        $output['side_spacing'] = min(
            200,
            max(
                0,
                (int) $output['side_spacing']
            )
        );

        if (
            isset($input['animation_speed']) &&
            is_numeric($input['animation_speed'])
        ) {
            $output['animation_speed'] = min(
                2,
                max(
                    0.05,
                    (float) $input['animation_speed']
                )
            );
        }

        $output['animation_enabled'] = !empty(
            $input['animation_enabled']
        ) ? 1 : 0;

        if (
            isset($input['position']) &&
            in_array(
                $input['position'],
                array(
                    'right',
                    'left',
                ),
                true
            )
        ) {
            $output['position'] = sanitize_key(
                $input['position']
            );
        }

        if (
            isset($input['services']) &&
            is_array($input['services'])
        ) {

            foreach ($this->services as $key => $default_name) {

                if (
                    !isset($input['services'][$key]) ||
                    !is_array($input['services'][$key])
                ) {
                    continue;
                }

                $service = $input['services'][$key];

                $name = isset($service['name'])
                    ? sanitize_text_field(
                        wp_unslash(
                            (string) $service['name']
                        )
                    )
                    : '';

                $link = isset($service['link'])
                    ? trim(
                        wp_unslash(
                            (string) $service['link']
                        )
                    )
                    : '';

                $description = isset($service['description'])
                    ? wp_kses_post(
                        wp_unslash(
                            (string) $service['description']
                        )
                    )
                    : '';

                if ('' !== $link) {

                    $link = esc_url_raw(
                        $link,
                        array(
                            'http',
                            'https',
                            'tel',
                            'mailto',
                        )
                    );
                }

                if ('' === $name) {

                    $name = sanitize_text_field(
                        $default_name
                    );
                }

                $output['services'][$key] = array(
                    'name' => $name,
                    'link' => $link,
                    'description' => $description,
                );
            }
        }

        return $output;
    }

    public function render_general_section(): void
    {

        echo '<p>';
        echo esc_html(
            'عنوان بالای دکمه قبل از باز شدن منو نمایش داده می‌شود و پس از باز شدن منو مخفی خواهد شد.'
        );
        echo '</p>';
    }

    public function render_services_section(): void
    {

        echo '<p>';
        echo esc_html(
            'برای نمایش هر سرویس، لینک آن را وارد کنید. اگر لینک خالی باشد، آن سرویس در سایت نمایش داده نمی‌شود.'
        );
        echo '</p>';
    }

    public function render_title_field(): void
    {

        $settings = $this->get_settings();

        $title = isset($settings['title'])
            ? sanitize_text_field(
                (string) $settings['title']
            )
            : '';

        ?>
        <input type="text" class="regular-text" name="<?php echo esc_attr(self::OPTION_NAME . '[title]'); ?>"
            value="<?php echo esc_attr($title); ?>" placeholder="<?php echo esc_attr('راه‌های ارتباطی با ما'); ?>" />

        <p class="description">
            <?php
            echo esc_html(
                'اگر این فیلد خالی باشد، هیچ عنوانی بالای دکمه نمایش داده نمی‌شود.'
            );
            ?>
        </p>
        <?php
    }

    public function render_color_field(array $args): void
    {

        $settings = $this->get_settings();

        $key = isset($args['key'])
            ? sanitize_key(
                $args['key']
            )
            : '';

        $value = isset($settings[$key])
            ? sanitize_hex_color(
                (string) $settings[$key]
            )
            : '';

        if (!$value) {
            $value = '#ffffff';
        }

        ?>
        <input type="color" name="<?php echo esc_attr(self::OPTION_NAME . '[' . $key . ']'); ?>"
            value="<?php echo esc_attr($value); ?>" aria-label="<?php echo esc_attr($key); ?>" />

        <input type="text" class="icodito-fcm-color-text" name="<?php echo esc_attr(self::OPTION_NAME . '[' . $key . ']'); ?>"
            value="<?php echo esc_attr($value); ?>" maxlength="7" pattern="#[0-9A-Fa-f]{6}" dir="ltr"
            aria-label="<?php echo esc_attr($key); ?>" />
        <?php
    }

    public function render_number_field(array $args): void
    {

        $settings = $this->get_settings();

        $key = isset($args['key'])
            ? sanitize_key(
                $args['key']
            )
            : '';

        $value = isset($settings[$key])
            ? $settings[$key]
            : '';

        $min = isset($args['min'])
            ? (string) $args['min']
            : '0';

        $max = isset($args['max'])
            ? (string) $args['max']
            : '100';

        $step = isset($args['step'])
            ? (string) $args['step']
            : '1';

        $suffix = isset($args['suffix'])
            ? (string) $args['suffix']
            : '';

        ?>
        <input type="number" class="small-text" name="<?php echo esc_attr(self::OPTION_NAME . '[' . $key . ']'); ?>"
            value="<?php echo esc_attr((string) $value); ?>" min="<?php echo esc_attr($min); ?>"
            max="<?php echo esc_attr($max); ?>" step="<?php echo esc_attr($step); ?>" />

        <?php if ('' !== $suffix): ?>

            <span>
                <?php echo esc_html($suffix); ?>
            </span>

        <?php endif; ?>
    <?php
    }

    public function render_animation_field(): void
    {

        $settings = $this->get_settings();

        $checked = !empty(
            $settings['animation_enabled']
        );

        ?>
        <label>
            <input type="checkbox" name="<?php echo esc_attr(self::OPTION_NAME . '[animation_enabled]'); ?>" value="1" <?php checked($checked, true); ?> />

            <?php
            echo esc_html(
                'فعال باشد'
            );
            ?>
        </label>
        <?php
    }

    public function render_position_field(): void
    {

        $settings = $this->get_settings();

        $position = isset($settings['position'])
            ? $settings['position']
            : 'right';

        ?>
        <select name="<?php echo esc_attr(self::OPTION_NAME . '[position]'); ?>">
            <option value="right" <?php selected($position, 'right'); ?>>
                <?php
                echo esc_html(
                    'پایین راست'
                );
                ?>
            </option>

            <option value="left" <?php selected($position, 'left'); ?>>
                <?php
                echo esc_html(
                    'پایین چپ'
                );
                ?>
            </option>
        </select>
        <?php
    }

    public function render_service_field(array $args): void
    {

        $settings = $this->get_settings();

        $key = isset($args['key'])
            ? sanitize_key(
                $args['key']
            )
            : '';

        $service = isset(
            $settings['services'][$key]
        ) && is_array(
            $settings['services'][$key]
        )
            ? $settings['services'][$key]
            : $this->defaults['services'][$key];

        $name = isset($service['name'])
            ? sanitize_text_field(
                (string) $service['name']
            )
            : '';

        $link = isset($service['link'])
            ? (string) $service['link']
            : '';

        $description = isset($service['description'])
            ? wp_kses_post(
                (string) $service['description']
            )
            : '';

        $base_name = self::OPTION_NAME .
            '[services][' .
            $key .
            ']';

        ?>
        <div class="icodito-fcm-service-fields">

            <div class="icodito-fcm-service-field">

                <label>
                    <span>
                        <?php
                        echo esc_html(
                            'نام نمایشی'
                        );
                        ?>
                    </span>

                    <input type="text" class="regular-text" name="<?php echo esc_attr($base_name . '[name]'); ?>"
                        value="<?php echo esc_attr($name); ?>" />
                </label>

            </div>

            <div class="icodito-fcm-service-field">

                <label>
                    <span>
                        <?php
                        echo esc_html(
                            'لینک'
                        );
                        ?>
                    </span>

                    <input type="text" class="large-text" name="<?php echo esc_attr($base_name . '[link]'); ?>"
                        value="<?php echo esc_attr($link); ?>" dir="ltr"
                        placeholder="<?php echo esc_attr('https://example.com/username'); ?>" />
                </label>

            </div>

            <div class="icodito-fcm-service-field">

                <label>
                    <span>
                        <?php
                        echo esc_html(
                            'توضیح'
                        );
                        ?>
                    </span>

                    <input type="text" class="large-text" name="<?php echo esc_attr($base_name . '[description]'); ?>"
                        value="<?php echo esc_attr(wp_strip_all_tags($description)); ?>" />
                </label>

            </div>

        </div>
        <?php
    }

    public function render_guide_section(): void
    {

        ?>
        <div class="icodito-fcm-guide">

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۱. لینک معمولی سایت یا صفحه'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'اگر سرویس یک صفحه یا پروفایل اینترنتی دارد، آدرس کامل آن را وارد کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            https://example.com/username
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۲. شماره تماس'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'برای اینکه با کلیک روی شماره، صفحه تماس تلفن باز شود، از tel: استفاده کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            tel:+989121234567
                        </code>

                <p>
                    <?php
                    echo esc_html(
                        'برای شماره‌های ایران بهتر است شماره را با کد کشور +98 وارد کنید.'
                    );
                    ?>
                </p>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۳. ایمیل'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'برای باز شدن برنامه ایمیل کاربر، از mailto: استفاده کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            mailto:info@example.com
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۴. واتساپ'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'برای واتساپ می‌توانید از لینک مستقیم شماره استفاده کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            https://wa.me/989121234567
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۵. تلگرام'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'برای کانال، گروه یا پروفایل تلگرام، لینک کامل آن را وارد کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            https://t.me/username
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۶. اینستاگرام'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'شناسه کاربری را به انتهای آدرس اینستاگرام اضافه کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            https://instagram.com/username
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۷. روبیکا، ایتا، بله، سروش، گپ و آی‌گپ'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'برای هرکدام، لینک مستقیم پروفایل، کانال، گروه یا صفحه مربوط به همان سرویس را وارد کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            https://example.com/username
                        </code>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۸. اپلیکیشن اختصاصی'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'اگر سرویس لینک مخصوص باز کردن اپلیکیشن دارد، همان Deep Link یا App Link را در فیلد لینک وارد کنید.'
                    );
                    ?>
                </p>

                <code dir="ltr">
                            appname://profile/username
                        </code>

                <p>
                    <?php
                    echo esc_html(
                        'همچنین اگر سرویس لینک HTTPS مخصوص باز کردن اپلیکیشن ارائه می‌دهد، همان لینک را وارد کنید.'
                    );
                    ?>
                </p>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۹. اگر لینک خالی باشد'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'آن سرویس به صورت کامل از منوی شناور حذف می‌شود و در سایت نمایش داده نخواهد شد.'
                    );
                    ?>
                </p>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۱۰. اگر نام خالی باشد'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'نام پیش‌فرض همان سرویس به صورت خودکار استفاده می‌شود.'
                    );
                    ?>
                </p>

            </div>

            <div class="icodito-fcm-guide-item">

                <h3>
                    <?php
                    echo esc_html(
                        '۱۱. اگر توضیح خالی باشد'
                    );
                    ?>
                </h3>

                <p>
                    <?php
                    echo esc_html(
                        'فقط نام سرویس نمایش داده می‌شود و فضای اضافی برای توضیح ایجاد نخواهد شد.'
                    );
                    ?>
                </p>

            </div>

        </div>
        <?php
    }


    private function render_author_support_box(): void
    {

        ?>
        <div class="icodito-author-support">
            <div class="icodito-author-support-icon" aria-hidden="true">❤️</div>

            <div class="icodito-author-support-content">
                <h3>این کد توسط آی کدیتو نوشته و بهینه شده است</h3>

                <p>
                    این کد با هدف ارائه یک راهکار کاربردی و رایگان توسط
                    <strong>آی کدیتو</strong>
                    تهیه و بهینه شده است.
                    در صورت مفید بودن این کد و استفاده از آن در سایت خود،
                    می‌توانید با حمایت از آی کدیتو به ادامه توسعه و انتشار
                    کدها و منابع رایگان کمک کنید.
                </p>

                <div class="icodito-author-support-links">
                    <a href="https://icodito.ir/" target="_blank" rel="noopener noreferrer">
                        وب‌سایت آی کدیتو
                    </a>

                    <a href="https://donito.me/icodito" target="_blank" rel="noopener noreferrer">
                        حمایت مالی از آی کدیتو
                    </a>
                </div>
            </div>
        </div>
        <?php
    }

    public function render_settings_page(): void
    {

        if (!current_user_can('manage_options')) {

            wp_die(
                esc_html(
                    'شما اجازه دسترسی به این صفحه را ندارید.'
                ),
                esc_html(
                    'عدم دسترسی'
                ),
                array(
                    'response' => 403,
                )
            );
        }

        ?>
        <div class="wrap icodito-fcm-admin">

            <?php $this->render_author_support_box(); ?>

            <h1>
                <?php
                echo esc_html(
                    'منوی شناور ارتباط'
                );
                ?>
            </h1>

            <form method="post" action="options.php">

                <?php

                settings_fields(
                    self::PAGE_SLUG
                );

                do_settings_sections(
                    self::PAGE_SLUG
                );

                submit_button(
                    'ذخیره تنظیمات'
                );

                ?>

            </form>

        </div>
        <?php
    }

    public function admin_enqueue_scripts(
        string $hook_suffix
    ): void {

        if (
            'settings_page_' . self::PAGE_SLUG !==
            $hook_suffix
        ) {
            return;
        }

        $style_handle = 'icodito-fcm-admin';

        wp_register_style(
            $style_handle,
            false,
            array(),
            self::VERSION
        );

        wp_enqueue_style(
            $style_handle
        );

        $css = '

			.icodito-fcm-admin {
				max-width: 1150px;
			}


			.icodito-author-support {
				display: flex;
				align-items: flex-start;
				gap: 16px;
				margin: 0 0 25px;
				padding: 20px 22px;
				background: #f8fafc;
				border: 1px solid #e2e8f0;
				border-right: 4px solid #00bcd4;
				border-radius: 10px 0 0 10px;
				direction: rtl;
				text-align: right;
				box-sizing: border-box;
			}

			.icodito-author-support-icon {
				display: flex;
				align-items: center;
				justify-content: center;
				flex: 0 0 44px;
				width: 44px;
				height: 44px;
				background: #ffffff;
				border: 1px solid #e2e8f0;
				border-radius: 50%;
				font-size: 20px;
				line-height: 1;
			}

			.icodito-author-support-content {
				flex: 1;
				min-width: 0;
			}

			.icodito-author-support-content h3 {
				margin: 0 0 8px;
				color: #1e293b;
				font-size: 15px;
				font-weight: 700;
				line-height: 1.8;
			}

			.icodito-author-support-content p {
				margin: 0;
				color: #64748b;
				font-size: 13px;
				line-height: 2;
			}

			.icodito-author-support-links {
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				gap: 8px;
				margin-top: 14px;
			}

			.icodito-author-support-links a {
				display: inline-flex;
				align-items: center;
				justify-content: center;
				padding: 7px 13px;
				background: #ffffff;
				color: #00a5bb;
				border: 1px solid #cbd5e1;
				border-radius: 7px;
				font-size: 12px;
				font-weight: 600;
				text-decoration: none;
				transition: all 0.2s ease;
			}

			.icodito-author-support-links a:hover {
				background: #00bcd4;
				color: #ffffff;
				border-color: #00bcd4;
			}

			.icodito-fcm-admin .form-table {
				margin-bottom: 35px;
			}

			.icodito-fcm-admin .form-table th {
				width: 220px;
			}

			.icodito-fcm-color-text {
				width: 90px;
				margin-right: 8px;
				direction: ltr;
			}

			.icodito-fcm-service-fields {
				display: grid;
				grid-template-columns:
					minmax(170px, 0.8fr)
					minmax(300px, 1.5fr)
					minmax(220px, 1fr);
				gap: 14px;
				max-width: 1000px;
			}

			.icodito-fcm-service-field label {
				display: block;
			}

			.icodito-fcm-service-field label > span {
				display: block;
				margin-bottom: 6px;
				font-weight: 600;
			}

			.icodito-fcm-service-field input {
				width: 100%;
			}

			.icodito-fcm-guide {
				display: grid;
				grid-template-columns:
					repeat(2, minmax(280px, 1fr));
				gap: 18px;
				margin: 10px 0 30px;
				max-width: 1050px;
			}

			.icodito-fcm-guide-item {
				padding: 20px;
				background: #fff;
				border: 1px solid #dcdcde;
				border-radius: 12px;
				box-shadow: 0 3px 12px rgba(0, 0, 0, 0.04);
			}

			.icodito-fcm-guide-item h3 {
				margin: 0 0 10px;
				font-size: 15px;
			}

			.icodito-fcm-guide-item p {
				margin: 7px 0;
				line-height: 1.8;
			}

			.icodito-fcm-guide-item code {
				display: block;
				padding: 10px 12px;
				margin: 10px 0;
				background: #f6f7f7;
				border-radius: 7px;
				direction: ltr;
				text-align: left;
				overflow-wrap: anywhere;
			}


			@media (max-width: 600px) {

				.icodito-author-support {
					gap: 12px;
					padding: 16px;
				}

				.icodito-author-support-icon {
					flex-basis: 38px;
					width: 38px;
					height: 38px;
					font-size: 17px;
				}

				.icodito-author-support-content h3 {
					font-size: 14px;
				}

				.icodito-author-support-content p {
					font-size: 12px;
				}

				.icodito-author-support-links {
					flex-direction: column;
					align-items: stretch;
				}

				.icodito-author-support-links a {
					width: 100%;
				}
			}

			@media (max-width: 900px) {

				.icodito-fcm-service-fields {
					grid-template-columns: 1fr;
				}

				.icodito-fcm-guide {
					grid-template-columns: 1fr;
				}
			}

			@media (max-width: 782px) {

				.icodito-fcm-admin .form-table th {
					width: auto;
				}

				.icodito-fcm-service-fields {
					max-width: 100%;
				}
			}
		';

        wp_add_inline_style(
            $style_handle,
            $css
        );

        $script_handle = 'icodito-fcm-admin-script';

        wp_register_script(
            $script_handle,
            false,
            array(),
            self::VERSION,
            true
        );

        wp_enqueue_script(
            $script_handle
        );

        $js = '

			document.addEventListener(
				"DOMContentLoaded",
				function () {

					document
						.querySelectorAll(
							".icodito-fcm-color-text"
						)
						.forEach(
							function (textInput) {

								textInput.addEventListener(
									"input",
									function () {

										var value =
											textInput.value.trim();

										if (
											/^#[0-9A-Fa-f]{6}$/.test(
												value
											)
										) {

											var colorInput =
												textInput
													.previousElementSibling;

											if (
												colorInput &&
												"color" ===
												colorInput.type
											) {
												colorInput.value =
													value;
											}
										}
									}
								);
							}
						);

					document
						.querySelectorAll(
							".icodito-fcm-admin input[type=color]"
						)
						.forEach(
							function (colorInput) {

								colorInput.addEventListener(
									"input",
									function () {

										var textInput =
											colorInput
												.nextElementSibling;

										if ( textInput ) {
											textInput.value =
												colorInput.value;
										}
									}
								);
							}
						);
				}
			);
		';

        wp_add_inline_script(
            $script_handle,
            $js
        );
    }

    public function enqueue_frontend_assets(): void
    {

        if (is_admin()) {
            return;
        }

        $settings = $this->get_settings();

        $has_service = false;

        foreach ($settings['services'] as $service) {

            if (
                is_array($service) &&
                !empty($service['link'])
            ) {
                $has_service = true;
                break;
            }
        }

        if (!$has_service) {
            return;
        }

        $handle = 'icodito-floating-contact-menu';

        wp_register_style(
            $handle,
            false,
            array(),
            self::VERSION
        );

        wp_enqueue_style(
            $handle
        );

        $button_color = sanitize_hex_color(
            (string) $settings['button_color']
        ) ?: '#00bcd4';

        $text_color = sanitize_hex_color(
            (string) $settings['text_color']
        ) ?: '#ffffff';

        $item_background = sanitize_hex_color(
            (string) $settings['item_background']
        ) ?: '#ffffff';

        $border_radius = min(
            50,
            max(
                0,
                absint(
                    $settings['border_radius']
                )
            )
        );

        $icon_size = min(
            64,
            max(
                12,
                absint(
                    $settings['icon_size']
                )
            )
        );

        $button_size = min(
            100,
            max(
                40,
                absint(
                    $settings['button_size']
                )
            )
        );

        $bottom_spacing = min(
            200,
            max(
                0,
                absint(
                    $settings['bottom_spacing']
                )
            )
        );

        $side_spacing = min(
            200,
            max(
                0,
                absint(
                    $settings['side_spacing']
                )
            )
        );

        $animation_speed = isset(
            $settings['animation_speed']
        ) && is_numeric(
            $settings['animation_speed']
        )
            ? min(
                2,
                max(
                    0.05,
                    (float) $settings['animation_speed']
                )
            )
            : 0.3;

        $position = 'left' === $settings['position']
            ? 'left'
            : 'right';

        $animation_class = !empty(
            $settings['animation_enabled']
        )
            ? 'icodito-fcm-animation-enabled'
            : 'icodito-fcm-animation-disabled';

        $css = "

			#icodito-floating-contact-menu {
				--icodito-fcm-button-color: {$button_color};
				--icodito-fcm-text-color: {$text_color};
				--icodito-fcm-item-background: {$item_background};
				--icodito-fcm-radius: {$border_radius}px;
				--icodito-fcm-icon-size: {$icon_size}px;
				--icodito-fcm-button-size: {$button_size}px;
				--icodito-fcm-bottom: {$bottom_spacing}px;
				--icodito-fcm-side: {$side_spacing}px;
				--icodito-fcm-animation-speed: {$animation_speed}s;

				position: fixed;
				bottom: var(--icodito-fcm-bottom);
				{$position}: var(--icodito-fcm-side);

				z-index: 999999;

				direction: rtl;

				font-family: inherit;

				box-sizing: border-box;

				display: flex;
				flex-direction: column;
				align-items: {$position};
			}

			#icodito-floating-contact-menu *,
			#icodito-floating-contact-menu *::before,
			#icodito-floating-contact-menu *::after {
				box-sizing: border-box;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-title {
				display: block;

				max-width:
					min(260px, calc(100vw - 30px));

				margin: 0 0 10px;

				padding: 8px 14px;

				border-radius: 999px;

				background:
					rgba(255, 255, 255, 0.92);

				color: #222222;

				font-size: 13px;

				font-weight: 500;

				line-height: 1.5;

				text-align: center;

				white-space: nowrap;

				overflow: hidden;

				text-overflow: ellipsis;

				box-shadow:
					0 7px 22px rgba(0, 0, 0, 0.11);

				backdrop-filter: blur(8px);
				-webkit-backdrop-filter: blur(8px);

				opacity: 1;

				visibility: visible;

				transform:
					translateY(0)
					scale(1);

				transform-origin: bottom center;

				transition:
					opacity
					var(--icodito-fcm-animation-speed)
					ease,

					transform
					var(--icodito-fcm-animation-speed)
					ease,

					visibility
					var(--icodito-fcm-animation-speed)
					ease;
			}

			#icodito-floating-contact-menu.is-open
			.icodito-fcm-title {
				opacity: 0;

				visibility: hidden;

				transform:
					translateY(6px)
					scale(0.96);

				pointer-events: none;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle {
				position: relative;

				display: flex;

				align-items: center;

				justify-content: center;

				width:
					var(--icodito-fcm-button-size);

				height:
					var(--icodito-fcm-button-size);

				padding: 0;

				margin: 0;

				border: 0;

				border-radius: 50%;

				background:
					var(--icodito-fcm-button-color);

				color:
					var(--icodito-fcm-text-color);

				box-shadow:
					0 10px 30px rgba(0, 0, 0, 0.16),
					0 3px 10px rgba(0, 0, 0, 0.10);

				cursor: pointer;

				-webkit-tap-highlight-color:
					transparent;

				overflow: hidden;

				isolation: isolate;

				backdrop-filter: blur(7px);

				-webkit-backdrop-filter: blur(7px);

				transition:
					transform
					var(--icodito-fcm-animation-speed)
					ease,

					box-shadow
					var(--icodito-fcm-animation-speed)
					ease,

					background-color
					var(--icodito-fcm-animation-speed)
					ease;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle:hover {
				transform: scale(1.07);

				box-shadow:
					0 14px 35px rgba(0, 0, 0, 0.20),
					0 5px 14px rgba(0, 0, 0, 0.12);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle:active {
				transform: scale(0.94);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle:focus-visible {
				outline:
					3px solid rgba(0, 188, 212, 0.45);

				outline-offset: 4px;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle-icon {
				position: relative;

				z-index: 2;

				display: flex;

				align-items: center;

				justify-content: center;

				width: 100%;

				height: 100%;

				transition:
					transform
					var(--icodito-fcm-animation-speed)
					ease,

					opacity
					var(--icodito-fcm-animation-speed)
					ease;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle-icon svg {
				width:
					calc(
						var(--icodito-fcm-button-size)
						* 0.46
					);

				height:
					calc(
						var(--icodito-fcm-button-size)
						* 0.46
					);

				fill: currentColor;

				stroke: currentColor;

				stroke-width: 1.8;

				stroke-linecap: round;

				stroke-linejoin: round;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-toggle-icon
			.icodito-fcm-icon-open,
			#icodito-floating-contact-menu
			.icodito-fcm-toggle-icon
			.icodito-fcm-icon-close {
				position: absolute;

				display: flex;

				align-items: center;

				justify-content: center;

				transition:
					opacity
					var(--icodito-fcm-animation-speed)
					ease,

					transform
					var(--icodito-fcm-animation-speed)
					ease;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-icon-open {
				opacity: 1;

				transform: rotate(0)
					scale(1);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-icon-close {
				opacity: 0;

				transform:
					rotate(-90deg)
					scale(0.5);
			}

			#icodito-floating-contact-menu.is-open
			.icodito-fcm-icon-open {
				opacity: 0;

				transform:
					rotate(90deg)
					scale(0.5);
			}

			#icodito-floating-contact-menu.is-open
			.icodito-fcm-icon-close {
				opacity: 1;

				transform:
					rotate(0)
					scale(1);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-ripple {
				position: absolute;

				z-index: 1;

				top: 50%;
				left: 50%;

				width: 0;
				height: 0;

				border-radius: 50%;

				background:
					rgba(255, 255, 255, 0.32);

				transform:
					translate(-50%, -50%);

				pointer-events: none;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-ripple.is-active {
				animation:
					icoditoFcmRipple
					0.55s
					ease-out
					forwards;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-list {
				position: absolute;

				bottom:
					calc(
						var(--icodito-fcm-button-size)
						+ 14px
					);

				{$position}: 0;

				display: flex;

				flex-direction: column;

				align-items: stretch;

				gap: 9px;

				width:
					min(
						300px,
						calc(100vw - 30px)
					);

				padding: 0;

				margin: 0;

				background: transparent;

				border: 0;

				pointer-events: none;

				opacity: 0;

				visibility: hidden;

				transform:
					translateY(12px)
					scale(0.96);

				transform-origin:
					bottom {$position};

				transition:
					opacity
					var(--icodito-fcm-animation-speed)
					ease,

					transform
					var(--icodito-fcm-animation-speed)
					ease,

					visibility
					var(--icodito-fcm-animation-speed)
					ease;
			}

			#icodito-floating-contact-menu.is-open
			.icodito-fcm-list {
				pointer-events: auto;

				opacity: 1;

				visibility: visible;

				transform:
					translateY(0)
					scale(1);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-item {
				display: flex;

				align-items: center;

				gap: 11px;

				width: 100%;

				min-width: 0;

				padding: 11px 13px;

				margin: 0;

				border: 0;

				border-radius:
					var(--icodito-fcm-radius);

				background:
					var(--icodito-fcm-item-background);

				color: #222222;

				text-decoration: none;

				box-shadow:
					0 8px 24px rgba(0, 0, 0, 0.12),
					0 2px 7px rgba(0, 0, 0, 0.07);

				transition:
					transform
					var(--icodito-fcm-animation-speed)
					ease,

					background-color
					var(--icodito-fcm-animation-speed)
					ease,

					box-shadow
					var(--icodito-fcm-animation-speed)
					ease;

				backdrop-filter: blur(8px);

				-webkit-backdrop-filter:
					blur(8px);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-item:hover {
				background: var(--icodito-fcm-item-hover, var(--icodito-fcm-item-background));

				transform:
					translateY(-2px);

				box-shadow:
					0 11px 28px rgba(0, 0, 0, 0.16),
					0 3px 9px rgba(0, 0, 0, 0.08);
			}

			#icodito-floating-contact-menu .icodito-fcm-item.aparat { --icodito-fcm-item-hover: #e94057; }
			#icodito-floating-contact-menu .icodito-fcm-item.eitaa { --icodito-fcm-item-hover: #f37f00; }
			#icodito-floating-contact-menu .icodito-fcm-item.soroush { --icodito-fcm-item-hover: #196ff0; }
			#icodito-floating-contact-menu .icodito-fcm-item.rubika { --icodito-fcm-item-hover: linear-gradient(135deg, #e74b50, #4c3683); }
			#icodito-floating-contact-menu .icodito-fcm-item.bale { --icodito-fcm-item-hover: #00a884; }
			#icodito-floating-contact-menu .icodito-fcm-item.igap { --icodito-fcm-item-hover: #57b952; }
			#icodito-floating-contact-menu .icodito-fcm-item.gap { --icodito-fcm-item-hover: #8056e0; }
			#icodito-floating-contact-menu .icodito-fcm-item.youtube { --icodito-fcm-item-hover: #ff3b30; }
			#icodito-floating-contact-menu .icodito-fcm-item.whatsapp { --icodito-fcm-item-hover: #25d366; }
			#icodito-floating-contact-menu .icodito-fcm-item.instagram { --icodito-fcm-item-hover: linear-gradient(135deg, #f7d43b, #ee3676, #9b2aa8); }
			#icodito-floating-contact-menu .icodito-fcm-item.telegram { --icodito-fcm-item-hover: #2ca0da; }
			#icodito-floating-contact-menu .icodito-fcm-item.email { --icodito-fcm-item-hover: #2563eb; }
			#icodito-floating-contact-menu .icodito-fcm-item.phone { --icodito-fcm-item-hover: #16a34a; }

			#icodito-floating-contact-menu .icodito-fcm-item:hover {
				color: #ffffff;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-item:focus-visible {
				outline:
					3px solid rgba(0, 188, 212, 0.38);

				outline-offset: 2px;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-icon {
				flex:
					0 0 var(--icodito-fcm-icon-size);

				display: flex;

				align-items: center;

				justify-content: center;

				width:
					var(--icodito-fcm-icon-size);

				height:
					var(--icodito-fcm-icon-size);
			}

			#icodito-floating-contact-menu
			.icodito-fcm-icon svg {
				display: block;

				width:
					var(--icodito-fcm-icon-size);

				height:
					var(--icodito-fcm-icon-size);

				fill: currentColor;

				stroke: none;
			}

			#icodito-floating-contact-menu .icodito-fcm-icon svg[data-icon-type=\"outline\"],
			#icodito-floating-contact-menu .icodito-fcm-toggle-icon svg[data-icon-type=\"outline\"] {
				fill: none;
				stroke: currentColor;
				stroke-width: 1.45;
				stroke-linecap: round;
				stroke-linejoin: round;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-content {
				flex: 1 1 auto;

				min-width: 0;

				display: flex;

				flex-direction: column;

				align-items: flex-start;

				gap: 2px;

				overflow: hidden;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-name {
				display: block;

				max-width: 100%;

				font-size: 14px;

				font-weight: 400;

				line-height: 1.5;

				color: inherit;

				white-space: nowrap;

				overflow: hidden;

				text-overflow: ellipsis;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-description {
				display: block;

				max-width: 100%;

				font-size: 11px;

				font-weight: 400;

				line-height: 1.5;

				opacity: 0.68;

				color: inherit;

				white-space: nowrap;

				overflow: hidden;

				text-overflow: ellipsis;
			}

			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-toggle,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-item,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-list,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-title,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-toggle-icon,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-icon-open,
			#icodito-floating-contact-menu
			.icodito-fcm-animation-disabled
			.icodito-fcm-icon-close {
				transition: none;
			}

			@keyframes icoditoFcmRipple {

				0% {
					width: 0;
					height: 0;
					opacity: 0.7;
				}

				100% {
					width:
						calc(
							var(--icodito-fcm-button-size)
							* 1.7
						);

					height:
						calc(
							var(--icodito-fcm-button-size)
							* 1.7
						);

					opacity: 0;
				}
			}

			@media (max-width: 600px) {

				#icodito-floating-contact-menu {
					#icodito-floating-contact-menu {
        --icodito-fcm-button-size: 52px;
        --icodito-fcm-side: 15px;
        --icodito-fcm-bottom: 15px;
    }

				#icodito-floating-contact-menu
				.icodito-fcm-title {
					max-width:
						calc(100vw - 30px);

					font-size: 12px;

					padding:
						7px 11px;
				}

				#icodito-floating-contact-menu
				.icodito-fcm-list {
					width:
						min(
							280px,
							calc(100vw - 30px)
						);

					bottom:
						calc(
							var(--icodito-fcm-button-size)
							+ 12px
						);

					gap: 7px;
				}

				#icodito-floating-contact-menu
				.icodito-fcm-item {
					padding: 9px 11px;

					gap: 9px;
				}

				#icodito-floating-contact-menu
				.icodito-fcm-name {
					font-size: 13px;
				}

				#icodito-floating-contact-menu
				.icodito-fcm-description {
					font-size: 10px;
				}
			}

			@media (prefers-reduced-motion: reduce) {

				#icodito-floating-contact-menu
				.icodito-fcm-toggle,
				#icodito-floating-contact-menu
				.icodito-fcm-item,
				#icodito-floating-contact-menu
				.icodito-fcm-list,
				#icodito-floating-contact-menu
				.icodito-fcm-title,
				#icodito-floating-contact-menu
				.icodito-fcm-toggle-icon,
				#icodito-floating-contact-menu
				.icodito-fcm-icon-open,
				#icodito-floating-contact-menu
				.icodito-fcm-icon-close {
					transition: none !important;

					animation: none !important;
				}
			}
		";

        wp_add_inline_style(
            $handle,
            $css
        );

        $script_handle =
            'icodito-floating-contact-menu-script';

        wp_register_script(
            $script_handle,
            false,
            array(),
            self::VERSION,
            true
        );

        wp_enqueue_script(
            $script_handle
        );

        $js = '

			document.addEventListener(
				"DOMContentLoaded",
				function () {

					var wrapper =
						document.getElementById(
							"icodito-floating-contact-menu"
						);

					if ( ! wrapper ) {
						return;
					}

					var toggle =
						wrapper.querySelector(
							".icodito-fcm-toggle"
						);

					var list =
						wrapper.querySelector(
							".icodito-fcm-list"
						);

					var ripple =
						wrapper.querySelector(
							".icodito-fcm-ripple"
						);

					var title =
						wrapper.querySelector(
							".icodito-fcm-title"
						);

					if (
						! toggle ||
						! list
					) {
						return;
					}

					var items =
						Array.prototype.slice.call(
							list.querySelectorAll(
								".icodito-fcm-item"
							)
						);

					function openMenu() {

						wrapper.classList.add(
							"is-open"
						);

						toggle.setAttribute(
							"aria-expanded",
							"true"
						);

						toggle.setAttribute(
							"aria-label",
							"بستن منوی ارتباط با ما"
						);

						items.forEach(
							function (item) {
								item.setAttribute(
									"tabindex",
									"0"
								);
							}
						);

						if ( items.length ) {
							items[0].focus();
						}
					}

					function closeMenu(
						restoreFocus
					) {

						wrapper.classList.remove(
							"is-open"
						);

						toggle.setAttribute(
							"aria-expanded",
							"false"
						);

						toggle.setAttribute(
							"aria-label",
							"باز کردن منوی ارتباط با ما"
						);

						items.forEach(
							function (item) {
								item.setAttribute(
									"tabindex",
									"-1"
								);
							}
						);

						if (
							restoreFocus &&
							document.activeElement !==
							toggle
						) {
							toggle.focus();
						}
					}

					function toggleMenu() {

						if (
							wrapper.classList.contains(
								"is-open"
							)
						) {
							closeMenu(true);
						} else {
							openMenu();
						}
					}

					toggle.addEventListener(
						"click",
						function (event) {

							event.preventDefault();

							if ( ripple ) {

								ripple.classList.remove(
									"is-active"
								);

								void ripple.offsetWidth;

								ripple.classList.add(
									"is-active"
								);
							}

							toggleMenu();
						}
					);

					document.addEventListener(
						"click",
						function (event) {

							if (
								! wrapper.contains(
									event.target
								)
							) {

								if (
									wrapper.classList.contains(
										"is-open"
									)
								) {
									closeMenu(false);
								}
							}
						}
					);

					document.addEventListener(
						"keydown",
						function (event) {

							if (
								event.key === "Escape" ||
								event.key === "Esc"
							) {

								if (
									wrapper.classList.contains(
										"is-open"
									)
								) {
									closeMenu(true);
								}

								return;
							}

							if (
								! wrapper.classList.contains(
									"is-open"
								)
							) {
								return;
							}

							if (
								event.key === "ArrowDown" ||
								event.key === "ArrowRight"
							) {

								if (
									! items.length
								) {
									return;
								}

								event.preventDefault();

								var current =
									items.indexOf(
										document.activeElement
									);

								if (
									current < 0
								) {
									items[0].focus();
								} else {
									items[
										(
											current + 1
										) %
										items.length
									].focus();
								}

								return;
							}

							if (
								event.key === "ArrowUp" ||
								event.key === "ArrowLeft"
							) {

								if (
									! items.length
								) {
									return;
								}

								event.preventDefault();

								var currentUp =
									items.indexOf(
										document.activeElement
									);

								if (
									currentUp < 0
								) {
									items[
										items.length - 1
									].focus();
								} else {
									items[
										(
											currentUp -
											1 +
											items.length
										) %
										items.length
									].focus();
								}

								return;
							}

							if (
								event.key === "Home" &&
								items.length
							) {

								event.preventDefault();

								items[0].focus();

								return;
							}

							if (
								event.key === "End" &&
								items.length
							) {

								event.preventDefault();

								items[
									items.length - 1
								].focus();

								return;
							}

							if (
								event.key === "Tab"
							) {

								var focusable =
									[toggle].concat(
										items
									);

								var currentIndex =
									focusable.indexOf(
										document.activeElement
									);

								if (
									event.shiftKey &&
									currentIndex === 0
								) {

									event.preventDefault();

									if (
										items.length
									) {
										items[
											items.length - 1
										].focus();
									} else {
										toggle.focus();
									}

								} else if (
									! event.shiftKey &&
									currentIndex ===
									focusable.length - 1
								) {

									event.preventDefault();

									toggle.focus();
								}
							}
						}
					);

					items.forEach(
						function (item) {

							item.addEventListener(
								"keydown",
								function (event) {

									if (
										event.key === " "
									) {
										event.preventDefault();
									}
								}
							);
						}
					);
				}
			);
		';

        wp_add_inline_script(
            $script_handle,
            $js
        );
    }

    public function render_frontend(): void
    {

        if (is_admin()) {
            return;
        }

        $settings = $this->get_settings();

        $visible_services = array();

        foreach (
            $this->services
            as $key => $default_label
        ) {

            if (
                !isset(
                $settings['services'][$key]
            ) ||
                !is_array(
                    $settings['services'][$key]
                )
            ) {
                continue;
            }

            $service =
                $settings['services'][$key];

            $link = isset(
                $service['link']
            )
                ? trim(
                    (string) $service['link']
                )
                : '';

            if ('' === $link) {
                continue;
            }

            $name = isset(
                $service['name']
            )
                ? sanitize_text_field(
                    (string) $service['name']
                )
                : '';

            if ('' === $name) {

                $name =
                    sanitize_text_field(
                        $default_label
                    );
            }

            $description =
                isset(
                $service['description']
            )
                ? wp_kses_post(
                    (string) 
                    $service['description']
                )
                : '';

            $visible_services[$key] =
                array(
                    'name' =>
                        $name,

                    'link' =>
                        $link,

                    'description' =>
                        $description,
                );
        }

        if (
            empty(
            $visible_services
        )
        ) {
            return;
        }

        $title = isset(
            $settings['title']
        )
            ? sanitize_text_field(
                (string) $settings['title']
            )
            : '';

        $animation_class =
            !empty(
            $settings['animation_enabled']
        )
            ? 'icodito-fcm-animation-enabled'
            : 'icodito-fcm-animation-disabled';

        ?>
        <div id="icodito-floating-contact-menu" class="<?php echo esc_attr($animation_class); ?>">

            <?php if ('' !== $title): ?>

                <div class="icodito-fcm-title" role="status" aria-live="polite">
                    <?php
                    echo esc_html(
                        $title
                    );
                    ?>
                </div>

            <?php endif; ?>

            <div id="icodito-fcm-list" class="icodito-fcm-list" role="menu"
                aria-label="<?php echo esc_attr('راه‌های ارتباطی'); ?>">

                <?php foreach (
                    $visible_services
                    as $key => $service
                ): ?>

                    <a class="icodito-fcm-item <?php echo esc_attr($key); ?>" href="<?php echo esc_url($service['link']); ?>"
                        role="menuitem" tabindex="-1" aria-label="<?php echo esc_attr($service['name']); ?>" <?php
                             if (
                                 $this->should_open_new_window(
                                     $service['link']
                                 )
                             ) {
                                 echo ' target="_blank" rel="noopener noreferrer"';
                             }
                             ?>>

                        <span class="icodito-fcm-icon" aria-hidden="true">
                            <?php
                            echo $this->get_service_icon(
                                $key
                            );
                            ?>
                        </span>

                        <span class="icodito-fcm-content">

                            <span class="icodito-fcm-name">
                                <?php
                                echo esc_html(
                                    $service['name']
                                );
                                ?>
                            </span>

                            <?php
                            if (
                                '' !==
                                trim(
                                    wp_strip_all_tags(
                                        $service['description']
                                    )
                                )
                            ):
                                ?>

                                <span class="icodito-fcm-description">
                                    <?php
                                    echo wp_kses_post(
                                        $service['description']
                                    );
                                    ?>
                                </span>

                            <?php endif; ?>

                        </span>

                    </a>

                <?php endforeach; ?>

            </div>

            <button type="button" class="icodito-fcm-toggle"
                aria-label="<?php echo esc_attr('باز کردن منوی ارتباط با ما'); ?>" aria-expanded="false"
                aria-controls="icodito-fcm-list" tabindex="0">

                <span class="icodito-fcm-toggle-icon" aria-hidden="true">

                    <span class="icodito-fcm-icon-open">
                        <?php
                        echo $this->get_toggle_open_icon();
                        ?>
                    </span>

                    <span class="icodito-fcm-icon-close">
                        <?php
                        echo $this->get_toggle_close_icon();
                        ?>
                    </span>

                </span>

                <span class="icodito-fcm-ripple" aria-hidden="true"></span>

            </button>

        </div>
        <?php
    }

    private function should_open_new_window(
        string $url
    ): bool {

        $scheme = wp_parse_url(
            $url,
            PHP_URL_SCHEME
        );

        if (
            !is_string($scheme)
        ) {
            return false;
        }

        return in_array(
            strtolower($scheme),
            array(
                'http',
                'https',
            ),
            true
        );
    }

    private function get_toggle_open_icon(): string
    {

        return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" data-icon-type="outline">
			<path d="M7.5 4.5a2 2 0 0 0-2 2v1.2c0 6.52 4.28 9.9 9.9 9.9h1.1a2 2 0 0 0 2-2v-1.05a1.2 1.2 0 0 0-.72-1.1l-2.38-1.02a1.2 1.2 0 0 0-1.39.3l-.78.9a8.2 8.2 0 0 1-3.85-3.85l.9-.78a1.2 1.2 0 0 0 .3-1.39L9.56 5.22a1.2 1.2 0 0 0-1.1-.72H7.5Z"/>
		</svg>';
    }

    private function get_toggle_close_icon(): string
    {

        return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" data-icon-type="outline">
			<path d="M6.5 6.5 17.5 17.5M17.5 6.5 6.5 17.5"/>
		</svg>';
    }

    private function get_service_icon(
        string $service
    ): string {

        $icons = array(

            'aparat' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M13.811 0.937l-2.946-.768c-.383-.106-.822-.167-1.276-.167-2.285 0-4.208 1.546-4.781 3.649l-.008.035-.735 2.777c2.376-2.939 5.783-4.962 9.665-5.517l.081-.009zM0.89 18.419l-.721 2.721c-.105.381-.166.819-.166 1.271 0 2.284 1.546 4.207 3.648 4.781l.035.008 2.81.749c-2.927-2.316-4.966-5.641-5.594-9.442l-.012-.088zM28.314 4.8l-3.152-.838c3.134 2.428 5.278 6.004 5.799 10.087l.008.075.866-3.278c.103-.377.162-.81.162-1.257 0-2.285-1.546-4.208-3.649-4.781l-.035-.008zM18.119 31.031l3.021.815c.381.105.819.166 1.271.166 2.284 0 4.207-1.546 4.781-3.648l.008-.035.852-3.203c-2.363 3.124-5.85 5.289-9.849 5.895l-.084.010zM16.002 2.126c-.001 0-.003 0-.005 0-7.664 0-13.876 6.213-13.876 13.876s6.213 13.876 13.876 13.876c7.664 0 13.876-6.213 13.876-13.876v0c0-7.662-6.21-13.874-13.871-13.876h-.0zM8.144 9.048c.365-1.842 1.968-3.212 3.89-3.212 2.188 0 3.962 1.774 3.962 3.962s-1.774 3.962-3.962 3.962c-.265 0-.523-.026-.773-.075l.025.004c-1.843-.364-3.214-1.967-3.214-3.891 0-.265.026-.525.076-.775l-.004.025zM13.909 21.037c-.367 1.839-1.968 3.206-3.889 3.206-2.188 0-3.962-1.774-3.962-3.962s1.774-3.962 3.962-3.962c.266 0 .526.026.777.076l-.025-.004c1.841.365 3.21 1.968 3.21 3.89 0 .267-.026.528-.077.781l.004-.025zM15.59 17.829c-.818-.163-1.426-.875-1.426-1.729 0-.973.788-1.761 1.761-1.761s1.761.788 1.761 1.761c0 .115-.011.227-.032.335l.002-.011c-.158.823-.873 1.437-1.731 1.437-.118 0-.234-.012-.346-.034l.011.002zM23.856 22.947c-.365 1.842-1.968 3.212-3.89 3.212-2.188 0-3.962-1.774-3.962-3.962s1.774-3.962 3.962-3.962c.265 0 .523.026.773.075l-.025-.004c1.843.364 3.214 1.967 3.214 3.891 0 .265-.026.525-.076.775l.004-.025zM21.233 15.604c-1.842-.365-3.212-1.968-3.212-3.89 0-2.188 1.774-3.962 3.962-3.962s3.962 1.774 3.962 3.962c0 .265-.026.523-.075.773l.004-.025c-.362 1.845-1.966 3.219-3.892 3.219-.265 0-.524-.026-.775-.076l.025.004z"/></svg>',

            'bale' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M31.937 14.541c-.042-.685-.16-1.37-.311-2.042-.397-1.814-1.13-3.549-2.128-5.114-2.253-3.543-5.952-6.143-10.067-7.008-.519-.127-1.144-.23-1.783-.288l-.051-.004c-.461-.053-.996-.084-1.537-.084-.319 0-.636.011-.951.031l.043-.002c-.718.026-1.399.109-2.061.244l.080-.014c-.599.083-1.181.25-1.761.406-.541.17-1.078.362-1.603.583-.594.248-1.075.485-1.542.746l.076-.039c-.535.29-.982.569-1.411.871l.044-.030c-.097.072-.208.144-.323.209l-.016.008c-1.095-.832-2.202-1.645-3.354-2.394-.317-.195-.624-.416-.979-.535-.582-.205-1.264-.048-1.722.368-.436.386-.624.988-.573 1.561.003.762-.003 1.527.006 2.288-.010.768-.003 1.542-.006 2.311s-.003 1.537.003 2.305q-.010 1.345 0 2.685-.010 1.305.003 2.611c.006 1.088-.051 2.183.070 3.267.086 1.117.317 2.224.65 3.29 1.517 4.957 5.61 9.059 10.59 10.509l.003.019c1.037.307 2.103.535 3.178.617 1.193.115 2.403.112 3.59-.070.637-.048 1.261-.205 1.885-.343.846-.226 1.548-.466 2.228-.745l-.121.044c.643-.275 1.28-.573 1.885-.932.597-.34 1.103-.674 1.586-1.038l-.037.027c.607-.45 1.142-.906 1.645-1.395l-.004.004c.391-.38.76-.777 1.107-1.192l.020-.025c.321-.38.642-.802.942-1.239l.035-.055c.275-.409.531-.835.778-1.264.253-.486.496-.973.714-1.475.237-.602.471-1.207.637-1.83.141-.512.294-1.024.346-1.552.134-.557.195-1.142.218-1.712.034-.354.053-.765.053-1.18 0-.496-.027-.985-.081-1.467l.005.059zM26.074 12.442c-.195.519-.538.963-.944 1.335-.355.352-.707.707-1.062 1.062-.377.377-.755.752-1.129 1.133-.362.358-.723.717-1.085 1.082-.394.393-.791.787-1.181 1.181-.448.451-.899.896-1.347 1.347-.423.426-.848.848-1.274 1.274s-.858.854-1.283 1.283c-.393.377-.752.797-1.197 1.12-.508.322-1.126.513-1.789.513-.023 0-.045 0-.068-.001l.003 0c-.755-.048-1.494-.345-2.038-.877q-2.51-2.51-5.024-5.026c-.409-.407-.685-.931-.832-1.485-.154-.765-.064-1.584.33-2.265.301-.528.762-.948 1.286-1.248.432-.209.94-.331 1.476-.331.133 0 .264.008.393.022l-.016-.001c.685.102 1.341.416 1.821.922.909.909 1.814 1.821 2.73 2.727.275-.262.541-.538.803-.81.384-.368.762-.746 1.129-1.133.365-.339.714-.698 1.059-1.059.247-.221.471-.464.707-.698.384-.375.758-.755 1.133-1.136.361-.345.71-.704 1.059-1.056.377-.368.746-.746 1.12-1.117.368-.374.82-.664 1.326-.838l.024-.007c.278-.081.597-.127.927-.127.382 0 .75.062 1.094.177l-.024-.007c.823.314 1.482.96 1.844 1.757.266.733.298 1.552.029 2.288z"/></svg>',

            'eitaa' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M9.308 0h13.38c4.907 0 8.92 4.008 8.92 8.914v4.302c-4.398 1.977-8.836 11.742-15.303 9.62-.533.379-1.76 1.938-1.847 3.122-2.239-.298-4.821-2.864-4.511-5.632-3.727-2.696-.649-7.673 2.306-9.676 6.335-4.293 15.129-.601 10.237 2.469-2.975 1.867-9.336 3.1-8.674-1.483-1.745.503-2.862 3.757-.761 5.452-1.946 1.912-1.572 5.427.508 6.581 2.104-5.451 9.427-4.739 12.385-11.246 2.226-4.895-1.074-10.472-7.673-9.616-4.98.647-9.648 4.847-11.982 9.829-2.369 5.055-2.016 11.824 2.848 15.235 5.724 4.015 11.817.297 15.508-4.561 2.175-2.864 4.076-6.036 6.957-7.868v7.627c0 4.906-4.014 8.926-8.92 8.926h-13.38c-4.906 0-8.92-4.014-8.92-8.92v-14.156c0-4.906 4.014-8.92 8.92-8.92z"/></svg>',

            'gap' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M27.834 26.92c-.88-.892-1.829-1.638-1.472-3.666.393-1.735.815-1.695 1.48-4.339.418-1.906.446-4.983-.811-7.647-1.366-2.98-3.633-5.113-6.885-6.415-2.429-.856-5.056-.949-7.53-.264-.985.324-5.936 1.784-8.073 7.643-.308.807-1.521 4.424.284 8.872 1.269 2.725 2.838 4.606 6.03 6.244 3.67 1.723 7.347 1.216 9.423.385 1.046-.422 1.829-.929 2.303-.868.474.109.981.446 1.662.669.795.207 1.541.332 2.871.296v0c.478-.045 1.488-.215.718-.912zM25.032 26.028c-1.026-.268-1.139-.47-1.971-.77-.227-.049-.88-.276-2.396.483-2.186 1.075-3.856 1.087-4.963 1.087-6.054-.211-8.56-4.898-8.811-5.332-1.817-3.013-1.387-5.908-1.257-7.019.807-3.763 2.599-5.304 3.516-6.127 2.851-2.498 5.579-2.506 7.169-2.506 1.914 0 3.787.58 5.365 1.662 2.076 1.314 3.726 3.653 4.367 5.859.868 2.907.373 5.385-.993 8.134-1.2 2.372-.024 4.529-.024 4.529zM11.968 19.119h2.705c.718-.008 1.306.568 1.314 1.285s-.568 1.306-1.285 1.314c-.008 0-.016 0-.028 0h-2.705c-.718.008-1.306-.568-1.314-1.285s.568-1.306 1.285-1.314c.012 0 .020 0 .028 0zM11.964 15.153h8c.714 0 1.294.58 1.294 1.293s-.58 1.294-1.294 1.294h-8c-.714 0-1.293-.58-1.293-1.294s.58-1.293 1.293-1.293zM17.276 11.163h2.705c.718-.008 1.302.568 1.31 1.285s-.568 1.302-1.285 1.31c-.008 0-.016 0-.028 0h-2.705c-.718-.008-1.302.568-1.31-1.285s.568-1.302 1.285-1.31c.012 0 .020 0 .028 0z"/></svg>',

            'igap' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M20.805 2.199q-.719.513-1.402 1.068-1.434 1.167-2.845 2.339M16.558 5.606l-1.036-.051M15.522 5.555l-.005-.552M7.7 14.729q-.438.515-.792.838-1.351 1.238-3.018 2.322M27.305 9.487q-1.732 1.432-2.444 2.002-.651.521-1.475 1.087M13.288 20.988l-.496-.124M27.442 17.002q-.322.278-1.21 1.021-5.855 4.896-8.528 7.11-1.091.904-2.153 1.571-.028.017-.029.049l-.005.093M9.484 24.342l3.814-3.341M18.269 20.86l-.534.145M13.298 21.001q.004-.006-.010-.012M20.805 2.199c-.479.342-.946.698-1.402 1.068-.956.778-1.904 1.557-2.845 2.339l-1.036-.051-.005-.552.001-2.708c0-.010-.011-.017-.020-.012-.001.001-.002.001-.003.002-1.722 1.724-3.445 3.447-5.169 5.167-.508.508-.836.857-.985 1.048-1.423 1.83-1.97 3.906-1.64 6.228-.292.343-.556.623-.792.838-.901.825-1.907 1.599-3.018 2.322-1.958-5.242-.266-11.068 4.218-14.413 1.672-1.247 3.558-2.024 5.658-2.33 2.413-.352 4.759-.001 7.039 1.053zM20.805 2.199c1.319.623 2.493 1.451 3.522 2.485 1.366 1.373 2.358 2.974 2.978 4.803-1.155.955-1.969 1.622-2.444 2.002-.434.347-.925.71-1.475 1.087-.16-1.384-.63-2.617-1.412-3.699-1.328-1.839-3.133-2.929-5.417-3.27.941-.781 1.89-1.561 2.845-2.339.455-.37.922-.726 1.402-1.068zM27.305 9.487c.247.736.423 1.483.529 2.243.047.341.071.767.072 1.276 0 .337 0 .675.001 1.013.001.393-.016.73-.051 1.010-.084.668-.221 1.326-.412 1.974-.215.186-.618.526-1.21 1.021-3.904 3.264-6.746 5.634-8.528 7.11-.727.602-1.445 1.126-2.153 1.571-.018.012-.028.028-.029.049l-.005.093-.008-.911c0-.022-.011-.033-.033-.033-2.134-.026-4.131-.546-5.993-1.562l3.814-3.341c1.479.501 2.958.502 4.436.004l.534-.145c.286-.089.529-.185.73-.287 2.053-1.047 3.419-2.647 4.099-4.797.315-.997.412-2.063.289-3.199.549-.377 1.041-.739 1.475-1.087.474-.38 1.289-1.047 2.444-2.002zM7.7 14.729c.472 2.795 2.349 5.1 4.962 6.118.017.006.060.013.13.019l.496.124c.009.004.013.008.010.012l-3.814 3.341c-2.624-1.498-4.489-3.649-5.594-6.453 1.111-.723 2.117-1.497 3.018-2.322.236-.216.5-.495.792-.838zM27.442 17.003c-.502 1.67-1.309 3.164-2.42 4.483-.195.231-.487.542-.877.932-2.863 2.867-5.731 5.735-8.603 8.604-.008.008-.022.004-.024-.007v-.003-4.164l.005-.093c.001-.021.011-.038.029-.049.708-.445 1.426-.969 2.153-1.571 1.782-1.476 4.624-3.846 8.528-7.11.592-.495.995-.835 1.21-1.021z"/></svg>',

            'instagram' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M21.333 16v-.001c0-2.945-2.388-5.333-5.333-5.333s-5.333 2.388-5.333 5.333 2.388 5.333 5.333 5.333c1.472 0 2.805-.597 3.771-1.561.964-.935 1.563-2.243 1.563-3.691 0-.028 0-.056-.001-.084v.004zM24.213 16c-.016 4.505-3.672 8.152-8.18 8.152-4.517 0-8.18-3.663-8.18-8.18s3.663-8.18 8.18-8.18c2.259 0 4.304.916 5.784 2.396 1.479 1.44 2.397 3.449 2.397 5.675 0 .048 0 .097-.001.145v-.007zM26.463 7.459v.003c0 1.060-.86 1.92-1.92 1.92s-1.92-.86-1.92-1.92.86-1.92 1.92-1.92c.531 0 1.011.215 1.357.563.341.335.553.801.553 1.317v.037zM16.009 2.872l-1.593-.011q-1.448-.011-2.199 0t-2.011.063c-.78.027-1.52.104-2.244.227l.097-.013c-.567.093-1.069.227-1.551.404l.057-.019c-1.392.567-2.476 1.649-3.029 3.005l-.013.036c-.159.424-.292.927-.379 1.444l-.007.049c-.109.625-.187 1.365-.212 2.119l-.001.028q-.052 1.261-.063 2.011t0 2.199.011 1.593-.011 1.593 0 2.199.063 2.011c.027.78.104 1.52.227 2.244l-.013-.097c.093.567.227 1.069.404 1.551l-.019-.057c.567 1.392 1.649 2.476 3.005 3.029l.036.013c.424.159.927.292 1.444.379l.049.007c.625.109 1.365.187 2.117.212l.028.001q1.261.052 2.011.063t2.199 0l1.584-.032 1.593.011q1.448.011 2.199 0t2.011-.063c.78-.027 1.52-.104 2.244-.227l-.097.013c.567-.093 1.069-.227 1.551-.404l-.057.019c1.392-.567 2.476-1.649 3.029-3.005l.013-.036c.159-.424.292-.927.379-1.444l.007-.049c.109-.625.187-1.365.212-2.117l.001-.028q.052-1.261.063-2.011t0-2.199-.011-1.593.011-1.593 0-2.199-.063-2.011c-.027-.78-.104-1.52-.227-2.244l.013.097c-.093-.567-.227-1.069-.404-1.551l.019.057c-.567-1.392-1.649-2.476-3.005-3.029l-.036-.013c-.424-.159-.927-.292-1.444-.379l-.049-.007c-.625-.109-1.365-.187-2.117-.212l-.028-.001q-1.261-.052-2.011-.063t-2.199 0zM32 16q0 4.771-.107 6.604c.007.135.012.292.012.449 0 4.889-3.964 8.853-8.853 8.853-.159 0-.316-.004-.472-.012l.021.001q-1.833.107-6.604.107t-6.604-.107c-.135.007-.292.012-.449.012-4.889 0-8.853-3.964-8.853-8.853 0-.159.004-.316.012-.472l-.001.021Q0 20.771 0 16t.107-6.604c-.007-.135-.012-.292-.012-.449C.095 4.058 4.059.094 8.948.094c.159 0 .316.004.472.012L9.399.105q1.833-.107 6.604-.107T22.607.105c.135-.007.292-.012.449-.012 4.889 0 8.853 3.964 8.853 8.853 0 .159-.004.316-.012.472L32 9.397Q32 11.23 32 16z"/></svg>',

            'rubika' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M15.049.864h.098c.027 2.374-.014 7.135-.014 7.135-2.27-1.273-4.556-2.517-6.824-3.794 1.486-.845 2.974-1.688 4.462-2.528.705-.398 1.463-.739 2.278-.813h.001zM15.142.864h.167c.883.079 1.682.5 2.441.927 1.416.799 2.831 1.601 4.243 2.407-2.278 1.263-4.581 2.546-6.862 3.804-.019-2.374.035-4.765.008-7.139l.002.001zM8.311 4.203l6.824 3.794-6.872 4.014s-.003-2.547.004-3.817c-.006-1.319.043-3.991.043-3.991zM22 4.197l.019.011c-.006 2.366 0 4.732 0 7.098-.004.232-.006.709-.006.709l-6.878-4.016s4.588-2.538 6.867-3.803h-.002zM22.014 4.209c1.516.862 3.021 1.742 4.526 2.621.728.409 1.5.862 1.898 1.633-2.132 1.181-6.427 3.556-6.427 3.556s-.003-.478 0-.71c0-2.366 0-4.732 0-7.098l.003-.001zM3.962 6.697c1.425-.833 4.344-2.493 4.344-2.493l-.038 7.808s-4.278-2.358-6.405-3.537c.463-.826 1.3-1.327 2.099-1.778zM1.379 11.586c.006-1.046-.013-2.158.481-3.111 2.13 1.178 6.403 3.537 6.403 3.537-2.298 1.329-4.585 2.678-6.884 4.008 0-1.478 0-2.955 0-4.434zM28.438 8.462c.419.783.48 1.694.457 2.566v5.006l-6.882-4.017s4.293-2.376 6.425-3.555zM1.379 16.020c2.297-1.333 4.584-2.679 6.883-4.008-.002 2.603-.002 5.206 0 7.809-.353-.147-.674-.357-1.011-.536-1.956-1.076-3.907-2.177-5.872-3.243v-.022zM22.012 12.017s6.882 4.008 6.882 4.017c-2.287 1.268-6.882 3.811-6.882 3.811.026-1.014-.007-2.026 0-3.041v-4.788h-.001zM1.379 16.042c1.964 1.067 3.913 2.167 5.872 3.244.337.178.658.389 1.011.536l.004.017c-2.11 1.231-4.22 2.462-6.331 3.694-.222-.336-.333-.733-.415-1.125-.133-.656-.141-1.322-.141-1.989v-4.377zM28.894 16.034c.003 1.536 0 3.072 0 4.608.022.985-.007 2.034-.532 2.903-1.9-1.111-6.352-3.7-6.352-3.7s4.596-2.543 6.883-3.811zM1.935 23.53c2.111-1.233 4.222-2.463 6.333-3.693-.014 2.602.004 5.204-.009 7.805-1.494-.843-2.985-1.692-4.472-2.548-.696-.411-1.408-.868-1.853-1.564zM8.268 19.838c2.293 1.266 4.574 2.542 6.867 3.808-2.289 1.333-6.872 4-6.875 3.997.013-2.601-.005-5.203.009-7.805v0zM22.001 19.85l.011-.005c.007 2.602-.014 5.205.011 7.807l-.017.008c-1.814-1.084-3.651-2.133-5.473-3.204-.459-.261-1.399-.811-1.399-.811s4.579-2.548 6.868-3.795zM22.012 19.845c.203.138 4.452 2.59 6.352 3.7-.27.461-.698.799-1.129 1.102-.696.468-1.438.859-2.161 1.281-1.017.575-2.028 1.162-3.051 1.722-.024-2.602-.004-5.205-.011-7.807v.002zM15.133 23.645v7.385c-.569-.084-1.19-.215-1.694-.504-1.727-.959-3.459-1.912-5.181-2.884 2.288-1.333 4.587-2.66 6.875-3.996zM15.133 23.645s.94.55 1.399.811c1.823 1.071 3.659 2.121 5.473 3.204-1.77.979-3.54 1.961-5.309 2.944-.442.245-.933.39-1.437.425h-.126v-7.385z"/></svg>',

            'soroush' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M31.531 13.864c-.11-1.007-.303-1.921-.576-2.8l.028.104c-.287-.985-.63-1.833-1.046-2.637l.038.081c-.545-1.074-1.15-1.998-1.842-2.849l.023.029c-1.242-1.528-2.736-2.796-4.427-3.756l-.077-.040c-.736-.404-1.496-.776-2.292-1.048-.611-.239-1.344-.453-2.1-.605l-.088-.015c-.744-.176-1.508-.22-2.264-.328h-1.772c-.244.044-.496.064-.744.088-3.138.326-5.942 1.545-8.212 3.394l.028-.022c-.436.336-.84.708-1.232 1.088-.856.868-1.632 1.824-2.264 2.864-.426.663-.822 1.428-1.146 2.229l-.034.095c-.314.725-.587 1.581-.776 2.469l-.016.091c-.164.708-.256 1.432-.32 2.152-.072 1.196-.036 2.396.152 3.576.183 1.16.466 2.195.847 3.181l-.036-.105c1.936 5.012 6.238 8.72 11.5 9.787l.1.017c2.988.592 6.156.292 8.972-.88 1.228.644 2.432 1.336 3.664 1.976h.252c.048-.069.096-.149.138-.232l.006-.012c.068-1.392.032-2.8.024-4.196 1.872-1.572 3.385-3.58 4.336-5.836.485-1.089.86-2.355 1.061-3.677l.011-.084c.116-.711.182-1.531.182-2.366 0-.611-.035-1.214-.104-1.806l.007.072zM22.391 18.956c-.116.901-.395 1.715-.806 2.445l.017-.034c-1.052 1.792-2.852 3.072-4.816 3.692-2.78.896-5.968.336-8.284-1.444-.648-.544-1.332-1.108-1.752-1.856.328.052.6.244.908.344 1.424.468 3.088.212 4.24-.76.808-.644 1.388-1.58 1.588-2.592.196-.94.048-1.912-.22-2.82-.232-.872-.564-1.72-.736-2.608-.14-.832-.148-1.684.016-2.512.235-1.125.731-2.109 1.424-2.921l-.008.009c1.292-1.456 3.244-2.328 5.2-2.156.020.016.056.044.072.056-.936.712-1.424 2.004-1.032 3.14.26.792.728 1.504 1.228 2.168.532.756 1.124 1.468 1.624 2.252.432.732.8 1.508 1.052 2.324.296 1.06.428 2.176.284 3.272z"/></svg>',

            'telegram' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M27.613 4.873s2.59-1.01 2.374 1.443c-.072 1.01-.719 4.545-1.223 8.369l-1.727 11.326s-.144 1.659-1.439 1.948-3.238-1.01-3.598-1.299c-.288-.216-5.396-3.463-7.195-5.05-.504-.433-1.079-1.299.072-2.309l7.555-7.214c.863-.866 1.727-2.886-1.871-.433L10.488 18.508s-1.151.721-3.31.072l-4.677-1.443s-1.727-1.082 1.223-2.164C10.919 11.582 19.769 8.119 27.613 4.873z"/></svg>',

            'whatsapp' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M25.314 22.594c-.386 1.092-1.918 1.994-3.141 2.258-.837.178-1.928.319-5.605-1.205-4.13-1.711-9.864-7.806-9.864-11.861 0-2.065 1.19-4.469 3.272-4.469 1.002 0 1.222.019 1.552.81.386.931 1.326 3.227 1.438 3.462.462.965-.47 1.53-1.147 2.37-.216.253-.461.527-.187.997.272.461 1.213 1.994 2.595 3.225 1.786 1.591 3.234 2.098 3.752 2.314.386.16.846.123 1.128-.178.357-.386.8-1.026 1.251-1.657.318-.451.723-.507 1.147-.347.286.099 3.926 1.789 4.08 2.06.114.197.114 1.128-.272 2.22zM16.003 0h-.008C7.174 0 .0 7.177 0 16c0 3.499 1.128 6.744 3.046 9.377l-1.994 5.946 6.149-1.965c2.53 1.674 5.549 2.642 8.802 2.642C24.824 32 32 24.823 32 16S24.824 0 16.003 0z"/></svg>',

            'youtube' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M31.681 9.6s-.313-2.206-1.275-3.175c-1.219-1.275-2.581-1.281-3.206-1.356-4.475-.325-11.194-.325-11.194-.325h-.012s-6.719 0-11.194.325c-.625.075-1.987.081-3.206 1.356C.631 7.394.325 9.6.325 9.6s-.319 2.588-.319 5.181v2.425c0 2.587.319 5.181.319 5.181s.313 2.206 1.269 3.175c1.219 1.275 2.819 1.231 3.531 1.369 2.563.244 10.881.319 10.881.319s6.725-.012 11.2-.331c.625-.075 1.988-.081 3.206-1.356.962-.969 1.275-3.175 1.275-3.175s.319-2.587.319-5.181v-2.425c-.006-2.588-.325-5.181-.325-5.181zM12.694 20.15v-8.994l8.644 4.513-8.644 4.481z"/></svg>',

            'email' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M4 7h24a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2Zm0 3 12 8 12-8V9L16 17 4 9v1Z"/></svg>',

            'phone' => '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M8.1 3.8a2.8 2.8 0 0 1 3.1 1.6l2 4.5a2.8 2.8 0 0 1-.5 3.1l-1.7 1.7a15.4 15.4 0 0 0 6.3 6.3l1.7-1.7a2.8 2.8 0 0 1 3.1-.5l4.5 2a2.8 2.8 0 0 1 1.6 3.1l-.5 2.4a3.5 3.5 0 0 1-3.4 2.8C12.8 29.1 2.9 19.2 2.9 7.7a3.5 3.5 0 0 1 2.8-3.4l2.4-.5Z"/></svg>',
        );

        if (!isset($icons[$service])) {
            return '<svg viewBox="0 0 32 32" aria-hidden="true" focusable="false"><circle cx="16" cy="16" r="9"/></svg>';
        }

        return $icons[$service];
    }
}

Icodito_Floating_Contact_Menu::instance();

پیشخوان وردپرس را یکبار رفرش کنید، در منو تنظیمات وردپرس گزینه ای با نام منو شناور ارتباط اضافه شده است ، از این قسمت لینک ها و تنظیمات را انجام دهید .

شخصی سازی لینک‌های شبکه‌های اجتماعی

floating 02 ساخت منوی شناور شبکه های اجتماعی در وردپرس با کد آماده

یکی از بخش‌هایی که باید بعد از نصب کد تنظیم شود، لینک سرویس‌های ارتباطی است.

برای مثال، اگر می‌خواهید گزینه تلگرام به کانال یا حساب شما متصل شود، باید لینک مربوط به حساب خودتان را جایگزین لینک نمونه موجود در کد کنید.

همین موضوع برای سایر سرویس‌ها نیز صدق می‌کند.

بنابراین بهتر است بعد از قرار دادن کد، تمام لینک‌های زیر را بررسی کنید:

  • لینک اینستاگرام
  • لینک تلگرام
  • لینک واتساپ
  • لینک یوتیوب
  • لینک آپارات
  • لینک ایتا
  • لینک بله
  • لینک روبیکا
  • لینک سروش
  • لینک گپ
  • لینک آی‌گپ
  • آدرس ایمیل
  • شماره تلفن

نکته مهم درباره لینک تماس و ایمیل

برای شماره تلفن می‌توان از لینک‌های tel: استفاده کرد تا در موبایل با لمس گزینه تماس، شماره تلفن برای کاربر باز شود.

برای ایمیل نیز می‌توان از لینک mailto: استفاده کرد تا انتخاب گزینه ایمیل، برنامه ایمیل پیش‌فرض کاربر را باز کند.

این دو قابلیت باعث می‌شوند منوی شناور فقط یک منوی شبکه اجتماعی نباشد و به یک ابزار کامل برای ارتباط سریع با کاربران تبدیل شود.

چه زمانی استفاده از منوی شناور پیشنهاد می‌شود؟

این نوع منو برای سایت هایی که ارتباط مستقیم با کاربران اهمیت زیادی دارد، کاربرد بیشتری دارد.

برای مثال:

  • فروشگاه‌های اینترنتی
  • سایت‌های آموزشی
  • سایت‌های شخصی
  • سایت‌های خدماتی
  • سایت‌های خبری و مجله‌ای
  • وب‌سایت‌های تولیدکنندگان محتوا
  • سایت‌هایی که در چند پیام‌رسان فعالیت دارند

اگر سایت شما فقط یک راه ارتباطی دارد، احتمالاً یک دکمه ساده تماس یا واتساپ می‌تواند کافی باشد؛ اما زمانی که چندین کانال ارتباطی دارید، منوی شناور گزینه مرتب‌تری برای نمایش آن‌ها خواهد بود.

نکات مهم قبل از استفاده

قبل از فعال کردن کد در سایت اصلی، چند مورد را بررسی کنید:

  1. از سایت خود نسخه پشتیبان تهیه کنید.
  2. لینک تمام شبکه‌های اجتماعی را بررسی کنید.
  3. شماره تلفن صحیح را وارد کنید.
  4. آدرس ایمیل را بررسی کنید.
  5. منو را در موبایل تست کنید.
  6. عملکرد لینک‌ها را در حالت ناشناس مرورگر بررسی کنید.
  7. مطمئن شوید منو روی محتوای مهم سایت قرار نمی‌گیرد.
  8. اگر سایت شما از سیستم کش استفاده می‌کند، بعد از تغییر کد کش را پاک کنید.

جمع بندی

یک منوی شناور می‌تواند راه ساده‌ای برای قرار دادن شبکه‌های اجتماعی و راه‌های ارتباطی مختلف در تمام صفحات سایت باشد.

کد ارائه‌شده در این مطلب با هدف ایجاد یک منوی شناور سبک و قابل شخصی‌سازی برای وردپرس آماده شده و سرویس‌هایی مانند اینستاگرام، تلگرام، واتساپ، یوتیوب، آپارات، ایتا، بله، روبیکا، سروش، گپ، آی‌گپ، ایمیل و تماس تلفنی را پوشش می‌دهد.

اگر به‌دنبال یک راهکار آماده برای نمایش لینک‌های ارتباطی در سایت وردپرسی خود هستید، می‌توانید فایل TXT کد را دریافت کرده و پس از تنظیم لینک‌های شخصی خود، آن را در سایت استفاده کنید.

سوالات متداول

بله، این کد با ساختار وردپرس آماده شده و برای استفاده در سایت های وردپرسی طراحی شده است.

بله. لینک‌ها و سرویس‌های موجود در کد قابل شخصی سازی هستند و می‌توانید لینک‌های مربوط به حساب‌های خود را جایگزین کنید.

بله. گزینه تماس تلفنی در ساختار منو در نظر گرفته شده و می‌تواند برای برقراری تماس مستقیم در دستگاه‌های سازگار استفاده شود.

بله. گزینه ایمیل نیز در منوی شناور قرار گرفته و می‌توان آن را به آدرس ایمیل موردنظر متصل کرد.

بله. رنگ‌های حالت Hover برای سرویس‌های مختلف در CSS تعریف شده‌اند و امکان تغییر و شخصی‌سازی آن‌ها وجود دارد.

خیر. کد به صورت قطعه کد آماده ارائه شده و می‌توان آن را با ابزارهای مدیریت Snippet در وردپرس مدیریت کرد.