feat: add action_dropdown macro with loading state support
- Create action_dropdown macro in dropdowns.html supporting: - Loading/disabled state via loading_var parameter - Custom loading label - Icon support - Primary/secondary variants - Update code quality dashboard to use new macro - Add Dropdowns section to components page with examples: - Basic dropdown - Action dropdown with loading state - Context menu (3-dot) - Variant showcase (primary, secondary, ghost) Architecture validation now passes with 0 errors and 0 warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -348,3 +348,81 @@
|
||||
<span x-show="{{ selected_var }} === '{{ value }}'" x-html="$icon('check', 'w-4 h-4')"></span>
|
||||
</button>
|
||||
{% 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'
|
||||
} %}
|
||||
<div class="relative">
|
||||
<button
|
||||
@click="{{ open_var }} = !{{ open_var }}"
|
||||
@click.outside="{{ open_var }} = false"
|
||||
:disabled="{{ loading_var }}"
|
||||
type="button"
|
||||
class="flex items-center px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 border rounded-lg focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed {{ variants[variant] }}"
|
||||
>
|
||||
<template x-if="!{{ loading_var }}">
|
||||
<span class="flex items-center">
|
||||
{% if icon %}
|
||||
<span x-html="$icon('{{ icon }}', 'w-4 h-4 mr-2')"></span>
|
||||
{% endif %}
|
||||
{{ label }}
|
||||
<span x-html="$icon('chevron-down', 'w-4 h-4 ml-1')"></span>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="{{ loading_var }}">
|
||||
<span class="flex items-center">
|
||||
<span x-html="$icon('spinner', 'w-4 h-4 mr-2')"></span>
|
||||
{{ loading_label }}
|
||||
</span>
|
||||
</template>
|
||||
</button>
|
||||
|
||||
<div
|
||||
x-show="{{ open_var }}"
|
||||
x-transition:enter="transition ease-out duration-100"
|
||||
x-transition:enter-start="transform opacity-0 scale-95"
|
||||
x-transition:enter-end="transform opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75"
|
||||
x-transition:leave-start="transform opacity-100 scale-100"
|
||||
x-transition:leave-end="transform opacity-0 scale-95"
|
||||
class="absolute z-50 mt-2 {{ width }} {{ positions[position] }} bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-1"
|
||||
>
|
||||
{{ caller() }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
Reference in New Issue
Block a user