Newer
Older
bugtrail / packages / web / src / components / CompactSelect.vue
<script setup lang="ts">
/**
 * Compact GnSelect for toolbars and side cards: kit.css styles GnSelect as a
 * 54px-tall, 600px-wide form control (div.form-group > label > select), which
 * is right for forms and wrong as a filter. This wrapper re-tightens it.
 */
import { GnSelect } from "gnexus-ui-kit/vue";

defineProps<{
  modelValue: string;
  options: { value: string; label: string }[];
  icon?: string;
  disabled?: boolean;
  /** pixel width of the control */
  width?: number;
}>();

defineEmits<{ (e: "update:modelValue", value: string): void }>();
</script>

<template>
  <div class="compact-select" :style="{ width: (width ?? 200) + 'px' }">
    <GnSelect
      :model-value="modelValue"
      :options="options"
      :icon="icon"
      :disabled="disabled"
      @update:model-value="$emit('update:modelValue', String($event))"
    />
  </div>
</template>

<style scoped>
.compact-select :deep(.form-group) {
  width: 100%;
  max-width: 100%;
  margin-bottom: 0;
}
.compact-select :deep(.form-group .label) {
  font-size: 12px;
}
.compact-select :deep(.form-group .label .select-wrap) {
  margin-top: 0;
}
.compact-select :deep(.form-group .label .select) {
  height: 38px;
  min-height: 38px;
  margin-top: 0;
  padding: 4px 34px 4px 12px;
  border-width: 1px;
  border-bottom-width: 3px;
  border-color: var(--ltt-border-strong, #2f334d);
  border-radius: 4px;
  font-size: 13px;
  letter-spacing: normal;
  background-color: var(--ltt-surface, #1f2335);
  color: var(--ltt-text, #c0caf5);
}
.compact-select :deep(.form-group .label .select:hover) {
  border-bottom-color: var(--ltt-text-dim, #787c99);
}
.compact-select :deep(.form-group .label .select:focus) {
  outline: 1px solid var(--ltt-warning, #e0af68);
  outline-offset: 1px;
  border-color: var(--ltt-accent, #7aa2f7);
  background-color: var(--ltt-surface, #1f2335);
}
/* the caret ::after is positioned for the 54px control — recenter for 38px */
.compact-select :deep(.form-group .label .select-wrap::after) {
  right: 12px;
  bottom: 50%;
  transform: translateY(50%);
  border-top-color: var(--ltt-text-dim, #787c99);
}
/* with an icon, keep the left padding for it and align the icon vertically */
.compact-select :deep(.form-group .label > .ph) {
  height: 38px;
  bottom: 0;
  width: 36px;
  justify-content: center;
  color: var(--ltt-text-dim, #787c99);
}
.compact-select :deep(.form-group .label .ph + .select-wrap .select),
.compact-select :deep(.form-group .label .ph + .select-wrap .select) {
  padding-left: 36px;
}
.compact-select :deep(select option) {
  color: var(--ltt-text, #c0caf5);
  background: var(--ltt-surface, #1f2335);
}
</style>