diff --git a/components/Accordion.php b/components/Accordion.php index 36708cc0ae..3c1ca48ac6 100644 --- a/components/Accordion.php +++ b/components/Accordion.php @@ -27,7 +27,7 @@ * ->add_item( 'About Course', '
Description...
' ) * ->render(); * - * // Multiple items + * // Multiple items, first open by default * Accordion::make() * ->add_item( 'About Course', 'Description...
' ) * ->add_item( 'Requirements', 'Prerequisites...
' ) @@ -35,11 +35,38 @@ * ->default_open( array( 0 ) ) * ->render(); * - * // With custom icon and template + * // Multiple items open by default (indices 0 and 2) * Accordion::make() - * ->add_item( 'Details', '', 'path/to/template.php', 'custom-icon' ) + * ->add_item( 'Overview', 'Course overview...
' ) + * ->add_item( 'Curriculum', 'Topics covered...
' ) + * ->add_item( 'FAQ', 'Common questions...
' ) + * ->default_open( array( 0, 2 ) ) + * ->render(); + * + * // Only one item open at a time (allow_multiple = false) + * Accordion::make() + * ->add_item( 'Section 1', 'Content 1...
' ) + * ->add_item( 'Section 2', 'Content 2...
' ) * ->allow_multiple( false ) * ->render(); + * + * // With custom icon per item + * Accordion::make() + * ->add_item( 'Resources', '', '', Icon::RESOURCES ) + * ->add_item( 'Downloads', '', '', Icon::DOWNLOAD_2 ) + * ->render(); + * + * // With a PHP template file as content + * Accordion::make() + * ->add_item( 'Details', '', get_template_directory() . '/partials/details.php' ) + * ->render(); + * + * // Extra HTML attributes on the wrapper + * Accordion::make() + * ->add_item( 'Notes', 'Some notes...
' ) + * ->attr( 'id', 'course-accordion' ) + * ->attr( 'class', 'my-custom-class' ) + * ->render(); * ``` * * @since 4.0.0 @@ -189,7 +216,7 @@ public function get(): string { 'multiple' => $this->multiple, 'defaultOpen' => $this->default_open, ); - $alpine_json = wp_json_encode( $alpine_config ); + $alpine_json = wp_json_encode( $alpine_config ); // Merge custom classes. $wrapper_classes = 'tutor-accordion'; @@ -206,9 +233,9 @@ public function get(): string { // Build items HTML. $items_html = ''; foreach ( $this->items as $index => $item ) { - $title = isset( $item['title'] ) ? $item['title'] : ''; - $icon = isset( $item['icon'] ) ? $item['icon'] : ''; - $panel_id = 'tutor-acc-panel-' . $index; + $title = isset( $item['title'] ) ? $item['title'] : ''; + $icon = isset( $item['icon'] ) ? $item['icon'] : ''; + $panel_id = 'tutor-acc-panel-' . $index; $trigger_id = 'tutor-acc-trigger-' . $index; $icon_html = $this->render_icon( $icon ); @@ -262,5 +289,4 @@ class="tutor-accordion-content" $items_html ); } - } diff --git a/components/Alert.php b/components/Alert.php index 6b864babf6..d03ba8ca82 100644 --- a/components/Alert.php +++ b/components/Alert.php @@ -20,11 +20,46 @@ * * Example usage: * ``` + * // Default (neutral) alert * Alert::make() - * ->text( 'This is an alert' ) + * ->text( 'Your changes have been saved.' ) + * ->render(); + * + * // Success alert with icon + * Alert::make() + * ->text( 'Course published successfully.' ) * ->variant( Alert::SUCCESS ) * ->icon( Icon::PRIME_CHECK_CIRCLE ) - * ->action( '' ) + * ->render(); + * + * // Info alert with action button + * Alert::make() + * ->text( 'You have an incomplete quiz. Resume where you left off.' ) + * ->variant( Alert::INFO ) + * ->icon( Icon::INFO ) + * ->action( '' ) + * ->render(); + * + * // Warning alert + * Alert::make() + * ->text( 'Your subscription expires in 3 days.' ) + * ->variant( Alert::WARNING ) + * ->icon( Icon::WARNING ) + * ->render(); + * + * // Error alert with custom icon size + * Alert::make() + * ->text( 'Payment failed. Please try again.' ) + * ->variant( Alert::ERROR ) + * ->icon( Icon::CLOSE_CIRCLE, 24, 24 ) + * ->render(); + * + * // Alert with extra HTML attributes + * Alert::make() + * ->text( 'Draft saved.' ) + * ->variant( Alert::SUCCESS ) + * ->attr( 'id', 'draft-alert' ) + * ->attr( 'x-show', 'showAlert' ) * ->render(); * ``` * diff --git a/components/AttachmentCard.php b/components/AttachmentCard.php index 53aeb7ef66..a978991994 100644 --- a/components/AttachmentCard.php +++ b/components/AttachmentCard.php @@ -18,13 +18,39 @@ * Class AttachmentCard * * Example Usage: + * ```php + * // Basic downloadable attachment * AttachmentCard::make() * ->file_name( 'lesson-plan.pdf' ) - * ->file_size( '1.2 MB' ) + * ->file_size( '1258291' ) // bytes — size_format() is applied internally * ->is_downloadable( true ) * ->action_attr( '@click', 'downloadFile()' ) * ->render(); * + * // Removable attachment (delete icon) + * AttachmentCard::make() + * ->file_name( 'assignment.docx' ) + * ->file_size( '524288' ) + * ->is_downloadable( false ) + * ->action_attr( '@click', 'removeFile(index)' ) + * ->render(); + * + * // With Alpine.js dynamic bindings on title and meta + * AttachmentCard::make() + * ->title_attr( 'x-text', 'file.name' ) + * ->meta_attr( 'x-text', 'formatBytes(file.size)' ) + * ->action_attr( '@click.stop', 'removeFile(index)' ) + * ->render(); + * + * // With extra attributes on the wrapper + * AttachmentCard::make() + * ->file_name( 'course-notes.pdf' ) + * ->file_size( '2097152' ) + * ->is_downloadable( true ) + * ->attr( 'data-id', '42' ) + * ->render(); + * ``` + * * @since 4.0.0 */ class AttachmentCard extends BaseComponent { diff --git a/components/Avatar.php b/components/Avatar.php index 345621d01d..66aac27efc 100644 --- a/components/Avatar.php +++ b/components/Avatar.php @@ -24,25 +24,49 @@ * Example usage: * * ```php - * Avatar with user object/ID + * // Avatar from a WP user ID (auto-resolves photo or initials) * Avatar::make() - * ->user($user_id) - * ->size(Size::SIZE_56) + * ->user( $user_id ) + * ->size( Size::SIZE_56 ) * ->render(); * - * Avatar with image source + * // Avatar from a WP_User object * Avatar::make() - * ->src('https://example.com/avatar.jpg') - * ->size(Size::SIZE_20) + * ->user( $user ) + * ->size( Size::SIZE_40 ) * ->bordered() * ->render(); * - * Avatar with initials + * // Avatar with explicit image URL * Avatar::make() - * ->initials('SK') - * ->size(Size::SIZE_32) - * ->rounded(false) + * ->src( 'https://example.com/avatar.jpg' ) + * ->alt( 'John Doe' ) + * ->size( Size::SIZE_32 ) * ->render(); + * + * // Avatar with initials fallback only + * Avatar::make() + * ->initials( 'JD' ) + * ->size( Size::SIZE_48 ) + * ->render(); + * + * // Avatar with square shape (no border-radius) + * Avatar::make() + * ->user( $user_id ) + * ->size( Size::SIZE_64 ) + * ->shape( 'square' ) + * ->render(); + * + * // Avatar with border and custom attributes + * Avatar::make() + * ->src( 'https://example.com/pic.jpg' ) + * ->size( Size::SIZE_20 ) + * ->bordered() + * ->attr( 'data-user-id', $user_id ) + * ->render(); + * + * // Retrieve HTML string without echoing + * $html = Avatar::make()->user( $user_id )->size( Size::SIZE_24 )->get(); * ``` * * @since 4.0.0 diff --git a/components/Badge.php b/components/Badge.php index a554e0cf6a..07d3b6bf52 100644 --- a/components/Badge.php +++ b/components/Badge.php @@ -20,16 +20,54 @@ * * Example usage: * ``` + * // Primary badge * Badge::make() - * ->label( 'Primary' ) + * ->label( 'New' ) * ->variant( Badge::PRIMARY ) + * ->render(); + * + * // Badge with SVG icon markup + * Badge::make() + * ->label( 'Certified' ) + * ->variant( Badge::SUCCESS ) * ->icon( '' ) * ->render(); * + * // Badge with icon name (SvgIcon slug) + * Badge::make() + * ->label( 'Warning' ) + * ->variant( Badge::WARNING ) + * ->icon( Icon::WARNING, 14, 14 ) + * ->render(); + * + * // Badge with icon as URL (img tag is generated) + * Badge::make() + * ->label( 'Verified' ) + * ->variant( Badge::SUCCESS_SOLID ) + * ->icon( 'https://example.com/check.png', 16, 16 ) + * ->render(); + * + * // Rounded (pill) badge * Badge::make() * ->label( 'Points: 20' ) + * ->variant( Badge::HIGHLIGHT ) * ->rounded() * ->render(); + * + * // Error / disabled badge without icon + * Badge::make() + * ->label( 'Inactive' ) + * ->variant( Badge::DISABLED ) + * ->render(); + * + * // Badge with no variant (default style) and extra attrs + * Badge::make() + * ->label( 'Draft' ) + * ->attr( 'data-status', 'draft' ) + * ->render(); + * + * // Retrieve HTML string without echoing + * $html = Badge::make()->label( 'Info' )->variant( Badge::INFO )->get(); * ``` * * @since 4.0.0 diff --git a/components/Button.php b/components/Button.php index 761fb4943f..4dbc310f26 100644 --- a/components/Button.php +++ b/components/Button.php @@ -15,7 +15,6 @@ use Tutor\Components\Constants\Size; use Tutor\Components\Constants\Variant; -use Tutor\Components\Constants\Color; defined( 'ABSPATH' ) || exit; @@ -24,13 +23,87 @@ * * Example usage: * ``` + * // Primary button (default) * Button::make() * ->label( 'Enroll Now' ) + * ->render(); + * + * // Button with size and variant + * Button::make() + * ->label( 'Save Changes' ) * ->size( Size::LARGE ) * ->variant( Variant::PRIMARY ) - * ->icon( 'tutor-icon-play' ) - * ->attr( 'data-id', 101 ) * ->render(); + * + * // Button with left icon + * Button::make() + * ->label( 'Add Course' ) + * ->icon( Icon::PLUS ) + * ->size( Size::MEDIUM ) + * ->variant( Variant::PRIMARY ) + * ->render(); + * + * // Button with right icon and custom icon size/color + * Button::make() + * ->label( 'Download' ) + * ->icon( Icon::DOWNLOAD_2, 'right', 18, Color::BRAND ) + * ->variant( Variant::OUTLINE ) + * ->render(); + * + * // Icon-only button (no visible label, uses aria-label) + * Button::make() + * ->label( 'Delete' ) + * ->icon( Icon::DELETE_2 ) + * ->icon_only() + * ->variant( Variant::GHOST ) + * ->size( Size::SMALL ) + * ->render(); + * + * // Disabled button + * Button::make() + * ->label( 'Submit' ) + * ->variant( Variant::PRIMARY ) + * ->disabled() + * ->render(); + * + * // Block (full-width) button + * Button::make() + * ->label( 'Continue' ) + * ->variant( Variant::PRIMARY ) + * ->block() + * ->render(); + * + * // Link-styled button rendered as tag + * Button::make() + * ->label( 'View Course' ) + * ->variant( Variant::LINK ) + * ->tag( 'a' ) + * ->attr( 'href', get_permalink( $course_id ) ) + * ->render(); + * + * // Destructive button + * Button::make() + * ->label( 'Delete Course' ) + * ->variant( Variant::DESTRUCTIVE ) + * ->size( Size::SMALL ) + * ->render(); + * + * // Secondary/outline button with data attribute + * Button::make() + * ->label( 'Cancel' ) + * ->variant( Variant::SECONDARY ) + * ->attr( 'data-id', $course_id ) + * ->render(); + * + * // Button with RTL-flippable directional icon + * Button::make() + * ->label( 'Next' ) + * ->icon( Icon::CHEVRON_RIGHT, 'right' ) + * ->flip_rtl() + * ->render(); + * + * // Retrieve HTML string without echoing + * $html = Button::make()->label( 'Get Started' )->variant( Variant::PRIMARY )->get(); * ``` * * @since 4.0.0 @@ -403,5 +476,4 @@ public function get(): string { return $this->component_string; } - } diff --git a/components/ConfirmationModal.php b/components/ConfirmationModal.php index 37d0025a85..d477917992 100644 --- a/components/ConfirmationModal.php +++ b/components/ConfirmationModal.php @@ -20,8 +20,7 @@ * Confirmation Modal Component Class. * * ``` - * // Example usage: - * + * // Basic delete confirmation * ConfirmationModal::make() * ->id( 'delete-course-modal' ) * ->title( 'Delete This Course?' ) @@ -30,14 +29,58 @@ * ->mutation_state( 'deleteMutation' ) * ->render(); * - * // With custom icon + * // With custom icon (icon name from Icon class) * ConfirmationModal::make() * ->id( 'delete-announcement-modal' ) * ->title( 'Delete This Announcement?' ) * ->message( 'This action cannot be undone.' ) - * ->icon( Icon::DELETE_2, 80 ) + * ->icon( Icon::DELETE_2, 80, 80 ) * ->confirm_handler( 'handleDeleteAnnouncement(payload?.announcementId)' ) * ->render(); + * + * // With icon as URL (img will be generated) + * ConfirmationModal::make() + * ->id( 'remove-student-modal' ) + * ->title( 'Remove Student?' ) + * ->message( 'The student will lose access to this course.' ) + * ->icon( 'https://example.com/icons/warning.svg', 100, 100 ) + * ->render(); + * + * // With custom button text + * ConfirmationModal::make() + * ->id( 'publish-course-modal' ) + * ->title( 'Publish Course?' ) + * ->message( 'The course will be visible to all students.' ) + * ->cancel_text( 'Not Yet' ) + * ->confirm_text( 'Publish Now' ) + * ->confirm_handler( 'publishCourse()' ) + * ->render(); + * + * // With custom modal width + * ConfirmationModal::make() + * ->id( 'wide-confirm-modal' ) + * ->title( 'Reset All Progress?' ) + * ->message( 'This will permanently reset all student progress records.' ) + * ->width( '520px' ) + * ->confirm_handler( 'resetProgress()' ) + * ->render(); + * + * // With fully custom confirm / cancel buttons + * ConfirmationModal::make() + * ->id( 'custom-btn-modal' ) + * ->title( 'Archive Course?' ) + * ->message( 'The course will be hidden from the catalog.' ) + * ->confirm_button( '' ) + * ->cancel_button( '' ) + * ->render(); + * + * // With inline HTML in the message (allowed tags) + * ConfirmationModal::make() + * ->id( 'delete-review-modal' ) + * ->title( 'Delete Review?' ) + * ->message( 'You are about to delete the review by .' ) + * ->confirm_handler( 'deleteReview(payload?.reviewId)' ) + * ->render(); * ``` * * @since 4.0.0 diff --git a/components/CourseFilter.php b/components/CourseFilter.php index 60af6fc4fc..975d2a74aa 100644 --- a/components/CourseFilter.php +++ b/components/CourseFilter.php @@ -23,11 +23,24 @@ * Class CourseFilter * * Example Usage: - * ``` + * ```php + * // Minimal — auto-fetches courses for the current user + * CourseFilter::make() + * ->render(); + * + * // With explicit courses list and total count * CourseFilter::make() * ->courses( $courses ) * ->count( $total_announcements ) * ->render(); + * + * // Pre-populate options from a custom courses array + * CourseFilter::make() + * ->courses( CourseModel::get_courses_by_instructor() ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = CourseFilter::make()->courses( $courses )->get(); * ``` * * @since 4.0.0 @@ -93,7 +106,7 @@ public static function get_course_filter_options( $courses = null ) { ); if ( null === $courses ) { - $courses = current_user_can( 'administrator' ) ? CourseModel::get_courses() : CourseModel::get_courses_by_instructor(); + $courses = current_user_can( 'manage_options' ) ? CourseModel::get_courses() : CourseModel::get_courses_by_instructor(); } if ( ! empty( $courses ) ) { diff --git a/components/DateFilter.php b/components/DateFilter.php index 1c948b6a86..143ea8dfdd 100644 --- a/components/DateFilter.php +++ b/components/DateFilter.php @@ -23,17 +23,58 @@ * Example usage: * * ```php + * // Single-date picker (bottom-start) + * DateFilter::make() + * ->type( DateFilter::TYPE_SINGLE ) + * ->render(); + * + * // Date-range picker (bottom-start, default) * DateFilter::make() * ->type( DateFilter::TYPE_RANGE ) - * ->placement( DateFilter::PLACEMENT_BOTTOM_START ) * ->render(); - * ``` * - * ```php + * // Date-range picker positioned at bottom-end * DateFilter::make() - * ->type( DateFilter::TYPE_SINGLE ) + * ->type( DateFilter::TYPE_RANGE ) * ->placement( DateFilter::PLACEMENT_BOTTOM_END ) * ->render(); + * + * // With a custom button label + * DateFilter::make() + * ->type( DateFilter::TYPE_RANGE ) + * ->label( 'Filter by date' ) + * ->render(); + * + * // Hide the initial label (show only icon until a range is selected) + * DateFilter::make() + * ->type( DateFilter::TYPE_RANGE ) + * ->hide_initial_label() + * ->render(); + * + * // Suppress label text entirely (icon-only button) + * DateFilter::make() + * ->type( DateFilter::TYPE_RANGE ) + * ->show_label( false ) + * ->render(); + * + * // Custom trigger button size and icon size + * DateFilter::make() + * ->type( DateFilter::TYPE_RANGE ) + * ->trigger_size( Size::X_SMALL ) + * ->icon_size( 14 ) + * ->render(); + * + * // Clear related query params when the filter changes (e.g. reset pagination) + * DateFilter::make() + * ->type( DateFilter::TYPE_RANGE ) + * ->clear_params( array( 'current_page' ) ) + * ->render(); + * + * // Extra attributes on the wrapper + * DateFilter::make() + * ->type( DateFilter::TYPE_SINGLE ) + * ->attr( 'id', 'my-date-filter' ) + * ->render(); * ``` * * @since 4.0.0 diff --git a/components/DropdownFilter.php b/components/DropdownFilter.php index 73e552dff7..a564deedb6 100644 --- a/components/DropdownFilter.php +++ b/components/DropdownFilter.php @@ -24,26 +24,70 @@ * Class DropdownFilter * * Example Usage: - * ``` - * // Basic dropdown with custom options + * ```php + * // Basic dropdown bound to URL query param (link-based navigation) + * DropdownFilter::make() + * ->options( $options ) + * ->query_param( 'status' ) + * ->render(); + * + * // With custom variant, size and search box * DropdownFilter::make() * ->options( $options ) * ->query_param( 'status' ) * ->variant( Variant::PRIMARY ) * ->size( Size::SMALL ) * ->search( true ) + * ->placeholder( __( 'Search status...', 'tutor' ) ) * ->render(); * - * // Course filter (convenience method) + * // JS callback on change (Alpine.js method name) instead of link navigation * DropdownFilter::make() - * ->options( $courses ) + * ->options( $options ) + * ->on_change( 'changeStatus' ) + * ->bind_active_value( 'currentStatus' ) + * ->render(); + * + * // Course filter convenience use-case + * DropdownFilter::make() + * ->options( CourseFilter::get_course_filter_options() ) * ->count( $total_items ) - * ->query_param( 'course_id' ) + * ->query_param( 'course-id' ) * ->variant( Variant::PRIMARY_SOFT ) * ->size( Size::X_SMALL ) * ->popover_size( Size::MEDIUM ) * ->position( Positions::BOTTOM_END ) * ->placeholder( __( 'Search Course', 'tutor' ) ) + * ->search( true ) + * ->render(); + * + * // Cumulative filtering — preserve existing query params via base_url + * DropdownFilter::make() + * ->options( $options ) + * ->query_param( 'category' ) + * ->base_url( remove_query_arg( 'current_page' ) ) + * ->render(); + * + * // Outline variant with custom button CSS + * DropdownFilter::make() + * ->options( $options ) + * ->variant( Variant::OUTLINE ) + * ->button_class( 'tutor-btn tutor-btn-outline tutor-btn-small my-custom-btn' ) + * ->render(); + * + * // Popover positioned bottom-end with large width + * DropdownFilter::make() + * ->options( $options ) + * ->query_param( 'type' ) + * ->position( Positions::BOTTOM_END ) + * ->popover_size( Size::LARGE ) + * ->render(); + * + * // Custom icon size for the chevron + * DropdownFilter::make() + * ->options( $options ) + * ->variant( Variant::PRIMARY ) + * ->icon_size( 14 ) * ->render(); * ``` * diff --git a/components/EmptyState.php b/components/EmptyState.php index 69251263f7..5925e81bdc 100644 --- a/components/EmptyState.php +++ b/components/EmptyState.php @@ -19,12 +19,40 @@ * Class EmptyState * * Example Usage: - * ``` + * ```php + * // Basic empty state (default icon and subtitle) + * EmptyState::make() + * ->title( 'No Courses Found' ) + * ->render(); + * + * // With title and subtitle * EmptyState::make() * ->title( 'No Data' ) * ->subtitle( 'Please check back later.' ) - * ->icon_path( 'path/to/icon.png' ) * ->render(); + * + * // With an image URL as icon + * EmptyState::make() + * ->title( 'No Announcements' ) + * ->subtitle( 'You have not posted any announcements yet.' ) + * ->icon_path( tutor()->url . 'assets/images/empty-announcements.svg' ) + * ->render(); + * + * // With raw SVG/HTML markup as icon + * EmptyState::make() + * ->title( 'No Results' ) + * ->icon( '' ) + * ->render(); + * + * // With extra CSS class on the wrapper + * EmptyState::make() + * ->title( 'Nothing Here Yet' ) + * ->subtitle( 'Start by creating your first course.' ) + * ->attr( 'class', 'tutor-mt-10' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = EmptyState::make()->title( 'No Reviews' )->get(); * ``` * * @since 4.0.0 diff --git a/components/FileUploader.php b/components/FileUploader.php index 7c998ca12d..fcaceddedf 100644 --- a/components/FileUploader.php +++ b/components/FileUploader.php @@ -22,32 +22,43 @@ /** * Class FileUploader * - * Example Usage (Native Multiple): + * Example Usage: + * ```php + * // Native single-file upload + * FileUploader::make() + * ->name( 'resume' ) + * ->accept( '.pdf,.doc' ) + * ->render(); + * + * // Native multiple-file upload with size/count limits * FileUploader::make() * ->name( 'course_attachments' ) * ->uploader_title( __( 'Upload Assignments', 'tutor' ) ) - * ->uploader_subtitle( __( 'Support PDF, DOCX (Max 20MB)', 'tutor' ) ) + * ->uploader_subtitle( __( 'Supports PDF, DOCX — max 20 MB each', 'tutor' ) ) * ->accept( '.pdf,.docx' ) * ->multiple( true ) * ->max_files( 3 ) * ->max_size( 20 * 1024 * 1024 ) * ->render(); * - * Example Usage (Native Single): + * // Image uploader (native file input, image preview variant) * FileUploader::make() - * ->name( 'resume' ) - * ->accept( '.pdf,.doc' ) + * ->variant( FileUploader::IMAGE_UPLOADER ) + * ->name( 'cover_photo' ) + * ->accept( '.jpg,.jpeg,.png,.webp' ) * ->render(); * - * Example Usage (WP Media Image): + * // WP Media Library — single image * FileUploader::make() * ->variant( FileUploader::IMAGE_UPLOADER ) * ->use_wp_media( true ) * ->wp_media_library_type( 'image' ) + * ->wp_media_title( __( 'Select Profile Photo', 'tutor' ) ) + * ->wp_media_button_text( __( 'Use This Photo', 'tutor' ) ) * ->name( 'profile_photo' ) * ->render(); * - * Example Usage (WP Media Multiple Documents): + * // WP Media Library — multiple documents * FileUploader::make() * ->use_wp_media( true ) * ->multiple( true ) @@ -55,21 +66,30 @@ * ->name( 'shared_files' ) * ->render(); * - * Example Usage (Native Image): + * // Custom icon, title, subtitle and button text * FileUploader::make() - * ->variant( FileUploader::IMAGE_UPLOADER ) - * ->name( 'cover_photo' ) - * ->render(); - * - * Example Usage (Custom UI): - * FileUploader::make() - * ->name( 'custom_upload' ) + * ->name( 'resources' ) * ->uploader_icon( Icon::RESOURCES ) + * ->uploader_icon_size( 32 ) * ->uploader_title( __( 'Resource Center', 'tutor' ) ) * ->uploader_subtitle( __( 'Add any relevant documents here', 'tutor' ) ) * ->uploader_button_text( __( 'Choose Resources', 'tutor' ) ) * ->render(); * + * // Required upload with an ID and Alpine.js callbacks + * FileUploader::make() + * ->name( 'assignment_file' ) + * ->id( 'assignment-upload' ) + * ->required( true ) + * ->accept( '.pdf' ) + * ->attr( 'onFileSelect', 'handleFileSelect' ) + * ->attr( 'onError', 'handleUploadError' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = FileUploader::make()->name( 'attachment' )->get(); + * ``` + * * @since 4.0.0 */ class FileUploader extends BaseComponent { diff --git a/components/InputField.php b/components/InputField.php index 89391dbccf..5dd44ecbd0 100644 --- a/components/InputField.php +++ b/components/InputField.php @@ -24,8 +24,16 @@ * InputField Component Class. * * Example usage: - * ``` - * // Text input with clear button + * ```php + * // Plain text input with label + * InputField::make() + * ->type( 'text' ) + * ->name( 'full_name' ) + * ->label( 'Full Name' ) + * ->placeholder( 'Enter your full name' ) + * ->render(); + * + * // Required text input with clear button and help text * InputField::make() * ->type( 'text' ) * ->name( 'full_name' ) @@ -33,8 +41,16 @@ * ->placeholder( 'Enter your full name' ) * ->required() * ->clearable() - * ->help_text( 'This is a helper text.' ) - * ->attr( 'x-bind', "register('full_name', { required: 'Name is required', minLength: { value: 2, message: 'Name must be at least 2 characters' } })") + * ->help_text( 'This name will appear on your certificate.' ) + * ->render(); + * + * // Text input with Alpine.js form validation binding + * InputField::make() + * ->type( 'text' ) + * ->name( 'username' ) + * ->label( 'Username' ) + * ->required() + * ->attr( 'x-bind', "register('username', { required: 'Username is required', minLength: { value: 3, message: 'Min 3 characters' } })" ) * ->render(); * * // Text input with left icon @@ -42,7 +58,40 @@ * ->type( 'text' ) * ->name( 'email' ) * ->label( 'Email' ) - * ->left_icon( '' ) + * ->left_icon( SvgIcon::make()->name( Icon::MAIL )->size( 18 )->get() ) + * ->render(); + * + * // Text input with right icon + * InputField::make() + * ->type( 'text' ) + * ->name( 'website' ) + * ->label( 'Website' ) + * ->right_icon( SvgIcon::make()->name( Icon::LINK )->size( 18 )->get() ) + * ->render(); + * + * // Email input + * InputField::make() + * ->type( 'email' ) + * ->name( 'email_address' ) + * ->label( 'Email Address' ) + * ->placeholder( 'you@example.com' ) + * ->render(); + * + * // Number input + * InputField::make() + * ->type( 'number' ) + * ->name( 'seats' ) + * ->label( 'Seats Available' ) + * ->value( '30' ) + * ->render(); + * + * // Password input with strength meter + * InputField::make() + * ->type( 'password' ) + * ->name( 'new_password' ) + * ->label( 'New Password' ) + * ->show_strength( true ) + * ->min_strength( 3 ) * ->render(); * * // Textarea @@ -50,17 +99,41 @@ * ->type( 'textarea' ) * ->name( 'bio' ) * ->label( 'Bio' ) + * ->placeholder( 'Tell us about yourself...' ) * ->render(); * * // Checkbox * InputField::make() * ->type( 'checkbox' ) * ->name( 'agree' ) - * ->label( 'I agree to terms' ) - * ->size( 'md' ) + * ->label( 'I agree to the terms and conditions' ) + * ->size( Size::MD ) + * ->render(); + * + * // Checkbox with HTML label (e.g., link inside label) + * InputField::make() + * ->type( 'checkbox' ) + * ->name( 'agree' ) + * ->label_html( 'I agree to the Terms' ) + * ->render(); + * + * // Intermediate (indeterminate) checkbox + * InputField::make() + * ->type( 'checkbox' ) + * ->name( 'select_all' ) + * ->label( 'Select All' ) + * ->intermediate( true ) * ->render(); * - * // Radio + * // Pre-checked checkbox + * InputField::make() + * ->type( 'checkbox' ) + * ->name( 'subscribe' ) + * ->label( 'Subscribe to newsletter' ) + * ->checked( true ) + * ->render(); + * + * // Radio button * InputField::make() * ->type( 'radio' ) * ->name( 'gender' ) @@ -68,15 +141,15 @@ * ->value( 'male' ) * ->render(); * - * // Switch + * // Toggle switch * InputField::make() * ->type( 'switch' ) * ->name( 'notifications' ) - * ->label( 'Enable notifications?' ) - * ->size( 'md' ) + * ->label( 'Enable email notifications' ) + * ->size( Size::MD ) * ->render(); * - * // InputField with error + * // Input with error state * InputField::make() * ->type( 'text' ) * ->name( 'username' ) @@ -84,22 +157,114 @@ * ->error( 'This field is required.' ) * ->render(); * - * // Select + * // Disabled input + * InputField::make() + * ->type( 'text' ) + * ->name( 'readonly_field' ) + * ->label( 'Read Only' ) + * ->value( 'Cannot change me' ) + * ->disabled() + * ->render(); + * + * // Loading state (e.g., while async options load) + * InputField::make() + * ->type( 'select' ) + * ->name( 'category' ) + * ->label( 'Category' ) + * ->loading( true ) + * ->loading_message( __( 'Loading categories...', 'tutor' ) ) + * ->render(); + * + * // Single select with flat options list + * InputField::make() + * ->type( 'select' ) + * ->name( 'country' ) + * ->label( 'Country' ) + * ->placeholder( 'Select a country' ) + * ->options( array( + * array( 'label' => 'United States', 'value' => 'us' ), + * array( 'label' => 'United Kingdom', 'value' => 'uk' ), + * array( 'label' => 'Canada', 'value' => 'ca' ), + * ) ) + * ->render(); + * + * // Select with icons and descriptions per option * InputField::make() - * ->type( 'select' ) - * ->name( 'interests' ) - * ->label( 'Interests' ) - * ->placeholder( 'Select your interests') - * ->required( 'Please select an interest') - * ->clearable() - * ->options( $interests ) - * ->multiple() - * ->searchable() - * ->size( 'md' ) - * ->max_selections( 2 ) - * ->help_text( 'This is a helper next.' ) - * ->render(); + * ->type( 'select' ) + * ->name( 'level' ) + * ->label( 'Course Level' ) + * ->options( array( + * array( 'label' => 'Beginner', 'value' => 'beginner', 'icon' => Icon::PLAY_LINE, 'description' => 'No prior knowledge needed' ), + * array( 'label' => 'Intermediate', 'value' => 'intermediate', 'icon' => Icon::BOOK, 'description' => 'Some experience required' ), + * array( 'label' => 'Advanced', 'value' => 'advanced', 'icon' => Icon::GRADUATION, 'description' => 'For experienced learners' ), + * ) ) + * ->render(); + * + * // Multi-select with search, clearable and max selections + * InputField::make() + * ->type( 'select' ) + * ->name( 'interests' ) + * ->label( 'Interests' ) + * ->placeholder( 'Select your interests' ) + * ->required( 'Please select an interest' ) + * ->clearable() + * ->options( $interests ) + * ->multiple() + * ->searchable() + * ->size( Size::MD ) + * ->max_selections( 2 ) + * ->help_text( 'You can pick up to 2 interests.' ) + * ->render(); * + * // Grouped select options + * InputField::make() + * ->type( 'select' ) + * ->name( 'topic' ) + * ->label( 'Topic' ) + * ->groups( array( + * array( + * 'label' => 'Development', + * 'options' => array( + * array( 'label' => 'PHP', 'value' => 'php' ), + * array( 'label' => 'JavaScript', 'value' => 'js' ), + * ), + * ), + * array( + * 'label' => 'Design', + * 'options' => array( + * array( 'label' => 'Figma', 'value' => 'figma' ), + * array( 'label' => 'Illustrator','value' => 'ai' ), + * ), + * ), + * ) ) + * ->render(); + * + * // Select with onChange callback and collapsable on selection + * InputField::make() + * ->type( 'select' ) + * ->name( 'sort_by' ) + * ->label( 'Sort By' ) + * ->options( $sort_options ) + * ->on_change( 'function(value){ handleSortChange(value); }' ) + * ->collapsable( true ) + * ->render(); + * + * // Time picker (12-hour, 15-minute interval) + * InputField::make() + * ->type( 'time' ) + * ->name( 'start_time' ) + * ->label( 'Start Time' ) + * ->selection_time_mode( 12 ) + * ->interval( 15 ) + * ->render(); + * + * // Small-size input + * InputField::make() + * ->type( 'text' ) + * ->name( 'search_term' ) + * ->placeholder( 'Search...' ) + * ->size( Size::SM ) + * ->render(); * ``` * * @since 4.0.0 diff --git a/components/Modal.php b/components/Modal.php index b2b400ed0e..4fe29337ff 100644 --- a/components/Modal.php +++ b/components/Modal.php @@ -18,38 +18,75 @@ * Modal Component Class. * * ``` - * // Example usage: + * // Basic modal with title and body text + * Modal::make() + * ->id( 'confirm-modal' ) + * ->title( 'Confirm Submission' ) + * ->body( 'Are you sure you want to submit this form?
' ) + * ->render(); * + * // Modal with title, subtitle and footer buttons * Modal::make() * ->id( 'confirm-modal' ) * ->title( 'Confirm Submission' ) - * ->subtitle( 'Are you sure you want to submit?' ) - * ->body( 'This action cannot be undone.' ) - * ->footer_buttons( '' ) + * ->subtitle( 'This action cannot be undone.' ) + * ->body( 'All data will be saved permanently.' ) + * ->footer_buttons( + * Button::make()->label( 'Cancel' )->variant( Variant::SECONDARY )->attr( '@click', "TutorCore.modal.closeModal('confirm-modal')" )->get() . + * Button::make()->label( 'Submit' )->variant( Variant::PRIMARY )->get() + * ) * ->footer_alignment( 'right' ) * ->render(); * - * // With template path + * // Modal loaded from a PHP template file * Modal::make() * ->id( 'course-modal' ) * ->title( 'Course Details' ) - * ->template( 'path/to/template.php' ) + * ->template( get_template_directory() . '/partials/course-modal.php', array( 'course_id' => $course_id ) ) * ->render(); * - * // Headless modal (no close button) + * // Non-closeable (headless) modal * Modal::make() * ->id( 'headless-modal' ) * ->closeable( false ) - * ->body( 'Learn more about this feature.
' ) + * ->footer_buttons( Button::make()->label( 'Got it' )->variant( Variant::PRIMARY )->get() ) + * ->footer_alignment( 'left' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = Modal::make()->id( 'my-modal' )->title( 'My Modal' )->body( 'Content' )->get(); * ``` * * @since 4.0.0 diff --git a/components/Nav.php b/components/Nav.php index 862532f2e7..47c5a76afa 100644 --- a/components/Nav.php +++ b/components/Nav.php @@ -24,44 +24,59 @@ * Responsible for rendering the nav component. * * - * //Example Usage : + * Example Usage: * - * ``` + * ```php + * // Simple link-only nav (primary, medium) + * $items = array( + * array( 'type' => 'link', 'label' => 'Dashboard', 'icon' => Icon::DASHBOARD, 'url' => '/dashboard', 'active' => true ), + * array( 'type' => 'link', 'label' => 'My Courses', 'icon' => Icon::BOOK, 'url' => '/my-courses' ), + * array( 'type' => 'link', 'label' => 'Wishlist', 'icon' => Icon::WISHLIST, 'url' => '/wishlist' ), + * ); + * + * Nav::make() + * ->items( $items ) + * ->render(); + * + * // Nav with a dropdown item * $items = array( - * array( - * 'type' => 'link', // 'link' or 'dropdown' - * 'label' => 'Wishlist', - * 'icon' => Icon::WISHLIST, - * 'url' => '#', - * 'active' => false, - * ), - * array( - * 'type' => 'dropdown', - * 'active' => true, - * 'options' => array( - * array( - * 'label' => 'Active', - * 'count => 4, - * 'icon' => Icon::PLAY_LINE, - * 'url' => '#', - * 'active' => false, - * ), - * array( - * 'label' => 'Enrolled', - * 'count => 4, - * 'icon' => Icon::ENROLLED, - * 'url' => '#', - * 'active' => true, - * ), - * ), - * ), + * array( + * 'type' => 'dropdown', + * 'active' => true, + * 'options' => array( + * array( 'label' => 'Active', 'count' => 4, 'icon' => Icon::PLAY_LINE, 'url' => '?status=active', 'active' => true ), + * array( 'label' => 'Enrolled', 'count' => 2, 'icon' => Icon::ENROLLED, 'url' => '?status=enrolled' ), + * array( 'label' => 'Wishlist', 'count' => 1, 'icon' => Icon::WISHLIST, 'url' => '?status=wishlist' ), + * ), + * ), + * array( 'type' => 'link', 'label' => 'Reviews', 'url' => '/reviews' ), * ); * - * echo Nav::make() - * ->items( array( $dropdown ) ) - * ->size( Size::SMALL ) - * ->variant( Variant::SECONDARY ) - * ->render(); + * Nav::make() + * ->items( $items ) + * ->size( Size::SMALL ) + * ->variant( Variant::SECONDARY ) + * ->render(); + * + * // Nav with count displayed on link items + * $items = array( + * array( 'type' => 'link', 'label' => 'Students', 'count' => 42, 'url' => '/students', 'active' => true ), + * array( 'type' => 'link', 'label' => 'Reviews', 'count' => 8, 'url' => '/reviews' ), + * ); + * + * Nav::make() + * ->items( $items ) + * ->size( Size::LARGE ) + * ->render(); + * + * // Extra attributes on the wrapper + * Nav::make() + * ->items( $items ) + * ->attr( 'id', 'student-nav' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = Nav::make()->items( $items )->get(); * ``` * * @since 4.0.0 diff --git a/components/Pagination.php b/components/Pagination.php index 27f183a800..bb7aac1e12 100644 --- a/components/Pagination.php +++ b/components/Pagination.php @@ -19,16 +19,51 @@ * * Responsible for rendering pagination component. * - * // Example Usage : + * Example Usage: * - * ``` - * Pagination::make() - * ->current( 2 ) - * ->total( 200 ) - * ->limit( tutor_utils()->get_option( 'pagination_per_page' ) ) - * ->prev( SvgIcon::make()->name( Icon::CHEVRON_LEFT_2 )->get() ) - * ->next( SvgIcon::make()->name( Icon::CHEVRON_RIGHT_2 )->get() ) - * ->render(); + * ```php + * // Minimal — current page from URL, default prev/next icons + * Pagination::make() + * ->current( (int) Input::get( 'current_page', 1 ) ) + * ->total( $total_items ) + * ->limit( 10 ) + * ->render(); + * + * // With custom prev/next icon markup + * Pagination::make() + * ->current( 2 ) + * ->total( 200 ) + * ->limit( tutor_utils()->get_option( 'pagination_per_page' ) ) + * ->prev( SvgIcon::make()->name( Icon::CHEVRON_LEFT_2 )->flip_rtl()->get() ) + * ->next( SvgIcon::make()->name( Icon::CHEVRON_RIGHT_2 )->flip_rtl()->get() ) + * ->render(); + * + * // Custom URL format (e.g., pretty-permalink pagination) + * Pagination::make() + * ->current( get_query_var( 'paged', 1 ) ) + * ->total( $total_items ) + * ->limit( 20 ) + * ->format( '/page/%#%/' ) + * ->render(); + * + * // Show all page links (no ellipsis collapsing) + * Pagination::make() + * ->current( 1 ) + * ->total( 50 ) + * ->limit( 5 ) + * ->show_all( true ) + * ->render(); + * + * // Extra CSS class on the nav wrapper + * Pagination::make() + * ->current( 1 ) + * ->total( 100 ) + * ->limit( 10 ) + * ->attr( 'class', 'tutor-mt-6' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = Pagination::make()->current( 1 )->total( 50 )->limit( 10 )->get(); * ``` * * @since 4.0.0 diff --git a/components/Popover.php b/components/Popover.php index ee084a439c..0fdd15e9b6 100644 --- a/components/Popover.php +++ b/components/Popover.php @@ -21,22 +21,86 @@ * Responsible for rendering popover component on button * at different placement positions with footer component and menu items. * - * Example Usage: Basic Popover - * ``` + * Example Usage: + * ```php + * // Basic popover with title and body (bottom-start by default) + * Popover::make() + * ->title( 'Information' ) + * ->body( 'This is a popover component.
' ) + * ->trigger( + * Button::make() + * ->label( 'Show Info' ) + * ->attr( 'x-ref', 'trigger' ) + * ->attr( '@click', 'toggle()' ) + * ->variant( Variant::PRIMARY ) + * ->get() + * ) + * ->render(); + * + * // Popover with close button in header + * Popover::make() + * ->title( 'Details' ) + * ->body( 'Here are the full details.
' ) + * ->closeable( true ) + * ->trigger( + * Button::make()->label( 'Details' )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Popover positioned top-end + * Popover::make() + * ->title( 'Help' ) + * ->body( 'Read the documentation for more help.
' ) + * ->placement( Positions::TOP_END ) + * ->trigger( + * Button::make()->label( '?' )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Popover with footer buttons * Popover::make() - * ->title( 'Basic' ) - * ->body( 'This is a popover component
' ) - * ->closeable( true ) - * ->trigger( - * Button::make() - * ->label( 'Show Popover' ) - * ->attr( 'x-ref', 'trigger' ) - * ->attr( '@click', 'toggle()' ) - * ->size( 'medium' ) - * ->variant( 'primary' ) - * ->get() - * ) - * ->render(); + * ->title( 'Confirm' ) + * ->body( 'Are you sure you want to proceed?
' ) + * ->footer( array( + * Button::make()->label( 'Cancel' )->variant( Variant::SECONDARY )->attr( '@click', 'hide()' )->get(), + * Button::make()->label( 'Confirm' )->variant( Variant::PRIMARY )->get(), + * ) ) + * ->footer_alignment( Positions::RIGHT ) + * ->trigger( + * Button::make()->label( 'Open' )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Popover as a context menu (menu items) + * Popover::make() + * ->menu_item( array( 'tag' => 'button', 'content' => 'Edit', 'icon' => SvgIcon::make()->name( Icon::EDIT )->size( 16 )->get(), 'attr' => array( '@click' => 'editItem()' ) ) ) + * ->menu_item( array( 'tag' => 'button', 'content' => 'Delete', 'icon' => SvgIcon::make()->name( Icon::DELETE_2 )->size( 16 )->get(), 'attr' => array( '@click' => 'deleteItem()', 'class' => 'tutor-text-critical' ) ) ) + * ->menu_min_width( '140px' ) + * ->trigger( + * Button::make()->icon( Icon::DOT_MENU_H )->icon_only()->variant( Variant::GHOST )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Menu item with right-aligned icon + * Popover::make() + * ->menu_item( array( 'tag' => 'a', 'content' => 'View Profile', 'icon' => SvgIcon::make()->name( Icon::ARROW_RIGHT )->size( 16 )->get(), 'icon_alignment' => Positions::RIGHT, 'attr' => array( 'href' => '#' ) ) ) + * ->trigger( + * Button::make()->label( 'Actions' )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Non-dismissible popover (click outside does NOT close it) + * Popover::make() + * ->title( 'Important' ) + * ->body( 'You must complete this step before continuing.
' ) + * ->dismissible( false ) + * ->trigger( + * Button::make()->label( 'Open' )->attr( 'x-ref', 'trigger' )->attr( '@click', 'toggle()' )->get() + * ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = Popover::make()->title( 'Tip' )->body( 'Hover for help.
' )->trigger( $btn )->get(); * ``` * * @since 4.0.0 diff --git a/components/PreviewTrigger.php b/components/PreviewTrigger.php index 6a072c608e..ceef6ea6b5 100644 --- a/components/PreviewTrigger.php +++ b/components/PreviewTrigger.php @@ -18,10 +18,19 @@ * Class PreviewTrigger * * Example Usage: - * ``` + * ```php + * // Render a preview trigger for a course * PreviewTrigger::make() - * ->id( 123 ) + * ->id( $course_id ) * ->render(); + * + * // Render a preview trigger for a lesson + * PreviewTrigger::make() + * ->id( $lesson_id ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = PreviewTrigger::make()->id( $course_id )->get(); * ``` * * @since 1.0.0 diff --git a/components/Progress.php b/components/Progress.php index 0c433703f0..80824366f7 100644 --- a/components/Progress.php +++ b/components/Progress.php @@ -22,20 +22,77 @@ * Progress Component Class. * * Example usage: - * ``` - * // Progress bar + * ```php + * // Basic animated progress bar (0–100) * Progress::make() * ->type( 'bar' ) * ->value( 75 ) - * ->animated() * ->render(); * - * // Progress circle + * // Progress bar without animation + * Progress::make() + * ->type( 'bar' ) + * ->value( 50 ) + * ->animated( false ) + * ->render(); + * + * // Progress bar with a specific size + * Progress::make() + * ->type( 'bar' ) + * ->value( 30 ) + * ->size( Size::MEDIUM ) + * ->render(); + * + * // Progress bar with brand variant color + * Progress::make() + * ->type( 'bar' ) + * ->value( 60 ) + * ->variant( Variant::BRAND ) + * ->render(); + * + * // Progress circle (percentage arc) * Progress::make() * ->type( 'circle' ) * ->value( 75 ) * ->render(); * + * // Progress circle — complete state (shows checkmark) + * Progress::make() + * ->type( 'circle' ) + * ->complete() + * ->render(); + * + * // Progress circle — locked state + * Progress::make() + * ->type( 'circle' ) + * ->locked() + * ->render(); + * + * // Progress circle without label + * Progress::make() + * ->type( 'circle' ) + * ->value( 40 ) + * ->show_label( false ) + * ->render(); + * + * // Progress circle with custom label text + * Progress::make() + * ->type( 'circle' ) + * ->value( 90 ) + * ->label( '9/10 done' ) + * ->render(); + * + * // Progress circle with custom colors and animation duration + * Progress::make() + * ->type( 'circle' ) + * ->value( 55 ) + * ->stroke_color( '#e0e0e0' ) + * ->progress_stroke_color( '#4CAF50' ) + * ->duration( 1500 ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = Progress::make()->type( 'bar' )->value( 80 )->get(); * ``` * * @since 4.0.0 diff --git a/components/SearchFilter.php b/components/SearchFilter.php index 8edcd099eb..b8c660a2f4 100644 --- a/components/SearchFilter.php +++ b/components/SearchFilter.php @@ -24,16 +24,50 @@ * Class SearchFilter * * Example Usage: - * ``` + * ```php + * // Minimal search form (uses current URL, param name = 'search') + * SearchFilter::make() + * ->render(); + * + * // With custom placeholder and input name + * SearchFilter::make() + * ->placeholder( 'Search students...' ) + * ->input_name( 'student_search' ) + * ->render(); + * + * // With explicit action URL and hidden inputs to preserve context * SearchFilter::make() - * ->form_id( 'my-search-form' ) - * ->placeholder( 'Search items...' ) - * ->hidden_inputs( array( 'type' => 'course' ) ) - * ->action( 'https://example.com/search' ) + * ->action( admin_url( 'admin.php?page=tutor-students' ) ) * ->input_name( 'search' ) - * ->method( 'GET' ) - * ->size( 'small' ) + * ->hidden_inputs( array( 'type' => 'enrolled', 'course_id' => $course_id ) ) + * ->render(); + * + * // Small-size search field + * SearchFilter::make() + * ->placeholder( 'Search...' ) + * ->size( Size::SMALL ) * ->render(); + * + * // Large-size search field + * SearchFilter::make() + * ->placeholder( 'Search courses...' ) + * ->size( Size::LARGE ) + * ->render(); + * + * // Custom form ID (useful when multiple search forms exist on the same page) + * SearchFilter::make() + * ->form_id( 'announcement-search-form' ) + * ->placeholder( 'Search announcements...' ) + * ->render(); + * + * // POST method (e.g., for AJAX-backed searches) + * SearchFilter::make() + * ->input_name( 'q' ) + * ->method( 'POST' ) + * ->render(); + * + * // Retrieve HTML without echoing + * $html = SearchFilter::make()->placeholder( 'Find a course...' )->get(); * ``` * * @since 4.0.0 @@ -222,7 +256,7 @@ public function get(): string { ob_start(); ?> -