{# Dropdown Macros =============== Reusable dropdown menu components with Alpine.js integration. Usage: from 'shared/macros/dropdowns.html' import dropdown, dropdown_menu, context_menu Basic dropdown: call dropdown('Actions', 'isDropdownOpen') dropdown_item('Edit', 'edit()', icon='pencil') dropdown_item('Delete', 'delete()', icon='trash', variant='danger') endcall Context menu (3-dot icon): call context_menu('itemMenu', 'isMenuOpen') dropdown_item('View', 'view()') dropdown_divider() dropdown_item('Delete', 'delete()', variant='danger') endcall #} {# Dropdown ======== A dropdown menu triggered by a button. Parameters: - label: Button label - open_var: Alpine.js variable for open state (default: 'isDropdownOpen') - position: 'left' | 'right' (default: 'right') - icon: Button icon (default: 'chevron-down') - variant: 'primary' | 'secondary' | 'ghost' (default: 'secondary') - size: 'sm' | 'md' (default: 'md') - width: Dropdown width class (default: 'w-48') #} {% macro dropdown(label, open_var='isDropdownOpen', position='right', icon='chevron-down', variant='secondary', size='md', width='w-48') %} {% set variants = { 'primary': 'text-white bg-purple-600 hover:bg-purple-700 border-transparent', 'secondary': 'text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 border-gray-300 dark:border-gray-600', 'ghost': 'text-gray-600 dark:text-gray-400 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-700 border-transparent' } %} {% set sizes = { 'sm': 'px-3 py-1.5 text-xs', 'md': 'px-4 py-2 text-sm' } %} {% set positions = { 'left': 'left-0', 'right': 'right-0' } %}
{{ caller() }}
{% endmacro %} {# Dropdown (External State) ========================= A dropdown that uses parent component's state. Parameters: - label: Button label - open_var: Alpine.js variable for open state - All other params same as dropdown() #} {% macro dropdown_external(label, open_var='isDropdownOpen', position='right', icon='chevron-down', variant='secondary', size='md', width='w-48') %} {% set variants = { 'primary': 'text-white bg-purple-600 hover:bg-purple-700 border-transparent', 'secondary': 'text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 border-gray-300 dark:border-gray-600', 'ghost': 'text-gray-600 dark:text-gray-400 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-700 border-transparent' } %} {% set sizes = { 'sm': 'px-3 py-1.5 text-xs', 'md': 'px-4 py-2 text-sm' } %} {% set positions = { 'left': 'left-0', 'right': 'right-0' } %}
{{ caller() }}
{% endmacro %} {# Context Menu (3-dot menu) ========================= An icon-only dropdown menu, commonly used for row actions. Parameters: - id: Unique ID for the menu - open_var: Alpine.js variable for open state (default: 'isMenuOpen') - position: 'left' | 'right' (default: 'right') - icon: Icon name (default: 'dots-vertical') - width: Dropdown width class (default: 'w-40') #} {% macro context_menu(id='contextMenu', open_var='isMenuOpen', position='right', icon='dots-vertical', width='w-40') %} {% set positions = { 'left': 'left-0', 'right': 'right-0' } %}
{{ caller() }}
{% endmacro %} {# Context Menu (External State) ============================= A context menu that uses parent component's state. Parameters: - open_var: Alpine.js variable for open state - position: 'left' | 'right' (default: 'right') - icon: Icon name (default: 'dots-vertical') - width: Dropdown width class (default: 'w-40') #} {% macro context_menu_external(open_var='isMenuOpen', position='right', icon='dots-vertical', width='w-40') %} {% set positions = { 'left': 'left-0', 'right': 'right-0' } %}
{{ caller() }}
{% endmacro %} {# Dropdown Item ============= An item within a dropdown menu. Parameters: - label: Item label - onclick: Alpine.js click handler - icon: Icon name (optional) - variant: 'default' | 'danger' (default: 'default') - href: URL if this should be a link - disabled: Whether the item is disabled #} {% macro dropdown_item(label, onclick=none, icon=none, variant='default', href=none, disabled=false) %} {% set variants = { 'default': 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-900 dark:hover:text-white', 'danger': 'text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 hover:text-red-700 dark:hover:text-red-300' } %} {% if href %} {% if icon %} {% endif %} {{ label }} {% else %} {% endif %} {% endmacro %} {# Dropdown Divider ================ A horizontal divider between dropdown items. #} {% macro dropdown_divider() %}
{% endmacro %} {# Dropdown Header =============== A non-clickable header within a dropdown. Parameters: - text: Header text #} {% macro dropdown_header(text) %}
{{ text }}
{% endmacro %} {# Select Dropdown =============== A dropdown that acts as a select input. Parameters: - label: Button label when nothing selected - selected_var: Alpine.js variable for selected value - selected_label_var: Alpine.js variable for selected label display - open_var: Alpine.js variable for open state - placeholder: Placeholder when nothing selected - width: Dropdown width class (default: 'w-full') #} {% macro select_dropdown(label='', selected_var='selected', selected_label_var='selectedLabel', open_var='isSelectOpen', placeholder='Select...', width='w-full') %}
{{ caller() }}
{% endmacro %} {# Select Option ============= An option within a select dropdown. Parameters: - value: Option value - label: Option label - selected_var: Alpine.js variable for selected value - selected_label_var: Alpine.js variable for selected label - open_var: Alpine.js variable to close dropdown #} {% macro select_option(value, label, selected_var='selected', selected_label_var='selectedLabel', open_var='isSelectOpen') %} {% endmacro %} {# Action Dropdown =============== A dropdown with loading/disabled state support for action buttons. Uses external Alpine.js state from parent component. Parameters: - label: Button label - loading_label: Label shown when loading (default: 'Loading...') - open_var: Alpine.js variable for open state - loading_var: Alpine.js variable for loading/disabled state - icon: Button icon (default: 'chevron-down') - position: 'left' | 'right' (default: 'right') - variant: 'primary' | 'secondary' (default: 'primary') - width: Dropdown width class (default: 'w-48') Usage: {% call action_dropdown( label='Run Scan', loading_label='Scanning...', open_var='scanDropdownOpen', loading_var='scanning', icon='search' ) %} {{ dropdown_item('Run All', 'runScan("all")') }} {{ dropdown_item('Architecture Only', 'runScan("architecture")') }} {% endcall %} #} {% macro action_dropdown(label, loading_label='Loading...', open_var='isDropdownOpen', loading_var='isLoading', icon=none, position='right', variant='primary', width='w-48') %} {% set variants = { 'primary': 'text-white bg-purple-600 hover:bg-purple-700 border-transparent focus:shadow-outline-purple', 'secondary': 'text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 border-gray-300 dark:border-gray-600 focus:shadow-outline-gray' } %} {% set positions = { 'left': 'left-0', 'right': 'right-0' } %}
{{ caller() }}
{% endmacro %}