SwitchableList
O componente SwitchableList é uma lista reordenável com suporte a seleção múltipla, busca, drag-and-drop e limites de seleção. É ideal para personalizações de colunas, seleção de filtros com limites e gerenciamento interativo de itens.
Exemplo
Clique para visualizar o código
vue
<script setup>
import LxSwitchableList from '@/components/LxSwitch/LxSwitchableList.vue';
const items = [
{ id: 'item1', label: 'Item 1', checked: true },
{ id: 'item2', label: 'Item 2', checked: true },
{ id: 'item3', label: 'Item 3', checked: false },
{ id: 'item4', label: 'Item 4', checked: false },
{ id: 'item5', label: 'Item 5', checked: false }
];
const handleSave = (newItems) => {
console.log('Items salvos:', newItems);
};
</script>
<template>
<div style="border: 1px solid var(--lx-silver-100); border-radius: 8px; padding: 1rem; overflow: hidden">
<LxSwitchableList id="example-list" :items="items" @save="handleSave" />
</div>
</template>Props
| Property | Descrição | Tipo | Padrão |
|---|---|---|---|
| items | Array de itens para exibição | Array | [] |
| maxSelections | Limite de items que podem ser selecionados | Number | null |
| selectedOnTop | Mostra items selecionados no topo | Boolean | true |
| showFooter | Exibe o footer com botões | Boolean | true |
| disabled | Desabilita a ordenação e seleção dos itens | Boolean | false |
| size | Tamanho dos labels e switches | String | md |
| headerConfig | Configurações do header (search, buttons) | Object | Ver constantes |
| itemConfig | Configurações de propriedades dos items | Object | Ver constantes |
| textConfig | Textos customizáveis do componente | Object | Ver constantes |
| behaviorConfig | Comportamentos do componente | Object | Ver constantes |
| containerClass | Classes CSS customizadas | String | '' |
Emits
| Event | Descrição |
|---|---|
| @save | Disparado quando usuário clica em "Salvar" |
Playground Interativo
Status:
Items selecionados: 2 / 5
Comportamento drag: ✓ Habilitado
headerConfig
textConfig
behaviorConfig
Outras Props
Clique para visualizar o código
vue
<script setup>
import { reactive, ref, computed } from 'vue';
import LxSwitchableList from '@/components/LxSwitch/LxSwitchableList.vue';
const listRef = ref(null);
const mockItems = [
{ id: 1, label: 'Coluna 1', checked: true, default: false },
{ id: 2, label: 'Coluna 2', checked: true, default: false },
{ id: 3, label: 'Coluna 3', checked: false, default: false },
{ id: 4, label: 'Coluna 4', checked: false, default: true },
{ id: 5, label: 'Coluna 5', checked: false, default: false }
];
const headerConfig = reactive({
description: 'Personalize as colunas conforme sua preferência',
searchable: true,
searchPlaceholder: 'Pesquise por uma coluna',
showRestoreDefault: true,
showEnableAll: true,
enableAllText: 'Ativar todos',
enableAllTextSelected: 'filtrados'
});
const itemConfig = reactive({
keyProperty: 'id',
labelProperty: 'label',
defaultProperty: 'default'
});
const textConfig = reactive({
clearButtonText: 'Limpar',
saveButtonText: 'Salvar',
fixedBadgeText: 'padrão',
disabledBadgeText: 'bloqueada',
emptyMessage: 'Nenhum item encontrado.'
});
const behaviorConfig = reactive({
draggable: true
});
const otherConfigs = reactive({
selectedOnTop: true,
maxSelections: null,
showFooter: true,
disabled: false,
containerClass: '',
size: 'md'
});
const displayItems = computed(() => listRef.value?.getCurrentItems() ?? mockItems);
const checkedCount = computed(() => displayItems.value.filter((i) => i.checked).length);
const configKey = computed(() => {
return JSON.stringify({
headerConfig,
itemConfig,
textConfig,
behaviorConfig,
otherConfigs
});
});
const handleSave = (items) => {
console.log('Items salvos:', items);
};
</script>
<template>
<div>
<div style="height: 500px; border: 2px solid var(--lx-silver-100); border-radius: 8px; padding: 1rem; overflow: hidden">
<LxSwitchableList
:key="configKey"
ref="listRef"
id="playground-list"
:items="mockItems"
:header-config="headerConfig"
:item-config="itemConfig"
:text-config="textConfig"
:behavior-config="behaviorConfig"
:selected-on-top="otherConfigs.selectedOnTop"
:max-selections="otherConfigs.maxSelections"
:show-footer="otherConfigs.showFooter"
:disabled="otherConfigs.disabled"
:container-class="otherConfigs.containerClass"
:size="otherConfigs.size"
@save="handleSave"
/>
</div>
<div class="mt-3 p-3 bg-light rounded">
<strong>Status:</strong>
<div class="mt-2 small">
<div>Items selecionados: {{ checkedCount }} / {{ displayItems.length }}</div>
<div v-if="otherConfigs.maxSelections">Limite de seleções: {{ otherConfigs.maxSelections }}</div>
<div>Comportamento drag: {{ behaviorConfig.draggable ? '✓ Habilitado' : '✗ Desabilitado' }}</div>
</div>
</div>
</div>
<div style="max-height: 600px; overflow-y: auto">
<div class="border rounded p-3">
<div class="mb-4">
<h6 class="border-bottom pb-2 mb-3">
<strong>headerConfig</strong>
</h6>
<div class="mb-3">
<label class="form-label mb-1">description</label>
<input v-model="headerConfig.description" type="text" class="form-control form-control-sm" placeholder="Deixe vazio para ocultar" />
</div>
<div class="mb-3">
<label class="form-check-label">
<input v-model="headerConfig.searchable" class="form-check-input" type="checkbox" />
searchable
</label>
</div>
<div class="mb-3">
<label class="form-label mb-1">searchPlaceholder</label>
<input v-model="headerConfig.searchPlaceholder" type="text" class="form-control form-control-sm" />
</div>
<div class="mb-3">
<label class="form-check-label">
<input v-model="headerConfig.showRestoreDefault" class="form-check-input" type="checkbox" />
showRestoreDefault
</label>
</div>
<div class="mb-3">
<label class="form-check-label">
<input v-model="headerConfig.showEnableAll" class="form-check-input" type="checkbox" />
showEnableAll
</label>
</div>
<div class="mb-3">
<label class="form-label mb-1">enableAllText</label>
<input v-model="headerConfig.enableAllText" type="text" class="form-control form-control-sm" />
</div>
<div class="mb-3">
<label class="form-label mb-1">enableAllTextSelected</label>
<input v-model="headerConfig.enableAllTextSelected" type="text" class="form-control form-control-sm" />
</div>
</div>
<!-- Text Config -->
<div class="mb-4">
<h6 class="border-bottom pb-2 mb-3">
<strong>textConfig</strong>
</h6>
<div class="mb-3">
<label class="form-label mb-1">clearButtonText</label>
<input v-model="textConfig.clearButtonText" type="text" class="form-control form-control-sm" />
</div>
<div class="mb-3">
<label class="form-label mb-1">saveButtonText</label>
<input v-model="textConfig.saveButtonText" type="text" class="form-control form-control-sm" />
</div>
<div class="mb-3">
<label class="form-label mb-1">fixedBadgeText</label>
<input v-model="textConfig.fixedBadgeText" type="text" class="form-control form-control-sm" />
</div>
</div>
<!-- Behavior Config -->
<div class="mb-4">
<h6 class="border-bottom pb-2 mb-3">
<strong>behaviorConfig</strong>
</h6>
<div class="mb-3">
<label class="form-check-label">
<input v-model="behaviorConfig.draggable" class="form-check-input" type="checkbox" />
draggable (Drag-and-drop)
</label>
</div>
</div>
<!-- Other Props -->
<div class="mb-4">
<h6 class="border-bottom pb-2 mb-3">
<strong>Outras Props</strong>
</h6>
<div class="mb-3">
<label class="form-check-label">
<input v-model="otherConfigs.selectedOnTop" class="form-check-input" type="checkbox" />
selectedOnTop
</label>
</div>
<div class="mb-3">
<label class="form-label mb-1">maxSelections</label>
<input v-model.number="otherConfigs.maxSelections" type="number" class="form-control form-control-sm" placeholder="null = sem limite" min="0" />
</div>
<div class="mb-3">
<label class="form-check-label">
<input v-model="otherConfigs.showFooter" class="form-check-input" type="checkbox" />
showFooter
</label>
</div>
<div class="mb-3">
<label class="form-check-label">
<input v-model="otherConfigs.disabled" class="form-check-input" type="checkbox" />
disabled (bloqueia seleção e reordenação)
</label>
</div>
<div class="mb-3">
<label class="form-label mb-1">containerClass</label>
<input v-model="otherConfigs.containerClass" type="text" class="form-control form-control-sm" placeholder="Classes CSS customizadas" />
</div>
<div class="mb-3">
<label class="form-label mb-1">size</label>
<select v-model="otherConfigs.size" class="form-select form-select-sm">
<option value="sm">Pequeno (sm)</option>
<option value="md">Médio (md)</option>
<option value="lg">Grande (lg)</option>
</select>
</div>
</div>
</div>
</div>
</template>
<style scoped>
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>Casos de Uso
O SwitchableList é útil em diversos cenários, como:
- Personalização de Colunas: Permitir usuários escolherem quais colunas visualizar em tabelas
- Filtros com Limite: Selecionar múltiplos filtros com um limite máximo de seleções
- Reordenação de Itens: Permitir drag-and-drop para reordenar items
- Gerenciamento de Permissões: Atribuir múltiplas permissões com controle visual
- Seleção de Features: Ativar/desativar features de um sistema
LxComponents