Skip to content

feat(VSwitch): add size prop#22882

Merged
J-Sek merged 1 commit into
devfrom
feat/vswitch-sizes
May 30, 2026
Merged

feat(VSwitch): add size prop#22882
J-Sek merged 1 commit into
devfrom
feat/vswitch-sizes

Conversation

@J-Sek
Copy link
Copy Markdown
Contributor

@J-Sek J-Sek commented May 30, 2026

closes #18334

Screencast.from.2026-05-31.01-12-51.webm

Markup:

<template>
  <v-app class="bg-surface">
    <v-defaults-provider :defaults="{ VSwitch: { inset, loading, hideDetails: true, density, trueIcon: icons ? '$complete' : undefined, falseIcon: icons ? '$close' : undefined } }">
      <v-container>
        <v-card min-height="360">
          <v-card-text class="d-flex">
            <div class="pa-2 flex-grow-1">
              <v-theme-provider theme="light">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" />
                    <v-switch :model-value="true" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
              <v-theme-provider theme="dark">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" />
                    <v-switch :model-value="true" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
            </div>
            <div class="pa-2 flex-grow-1">
              <v-theme-provider theme="light">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" color="primary" />
                    <v-switch :model-value="true" color="primary" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
              <v-theme-provider theme="dark">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" color="primary" />
                    <v-switch :model-value="true" color="primary" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
            </div>
            <div class="pa-2 flex-grow-1">
              <v-theme-provider theme="light">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" color="primary" />
                    <v-switch :model-value="true" color="primary" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
              <v-theme-provider theme="dark">
                <v-sheet>
                  <v-row class="justify-center align-center py-12 border-md" gap="24">
                    <v-switch :model-value="false" color="primary" />
                    <v-switch :model-value="true" color="primary" />
                  </v-row>
                </v-sheet>
              </v-theme-provider>
            </div>
            <v-defaults-provider :defaults="{ VSwitch: { disabled: true } }">
              <div class="pa-2 flex-grow-1">
                <v-theme-provider theme="light">
                  <v-sheet>
                    <v-row class="justify-center align-center py-12 border-md" gap="24">
                      <v-switch :model-value="false" color="primary" />
                      <v-switch :model-value="true" color="primary" />
                    </v-row>
                  </v-sheet>
                </v-theme-provider>
                <v-theme-provider theme="dark">
                  <v-sheet>
                    <v-row class="justify-center align-center py-12 border-md" gap="24">
                      <v-switch :model-value="false" color="primary" />
                      <v-switch :model-value="true" color="primary" />
                    </v-row>
                  </v-sheet>
                </v-theme-provider>
              </div>
            </v-defaults-provider>
          </v-card-text>
        </v-card>
        <v-card class="mt-4">
          <v-card-text class="d-flex align-end ga-8">
            <div v-for="size in sizes" :key="size" class="d-flex flex-column align-center ga-3">
              <v-switch :model-value="true" :size="size" color="primary" />
              <v-switch :model-value="false" :size="size" color="primary" />
              <span class="text-caption">{{ size }}</span>
            </div>
          </v-card-text>
        </v-card>
        <v-card class="mt-4">
          <v-card-text>
            <div class="pa-2 flex-grow-1">
              <v-row>
                <v-col v-for="[color, thumbColor] in colors" :key="color" cols="12" md="4" sm="6">
                  <div class="d-flex align-center ga-3">
                    <v-avatar :color="thumbColor ?? color" size="32" />
                    <v-switch
                      v-model="model"
                      :color="color"
                      :label="color"
                      :thumb-color="thumbColor"
                      :value="color"
                      hide-details
                    />
                  </div>
                </v-col>
              </v-row>
            </div>
          </v-card-text>
        </v-card>
      </v-container>
    </v-defaults-provider>
    <div class="d-flex flex-column ga-2 ma-3 position-absolute bottom-0 right-0">
      <v-btn
        class="align-self-end"
        icon="mdi-palette"
        variant="tonal"
      >
        <v-icon />
        <v-menu
          :close-on-content-click="false"
          activator="parent"
          offset="8"
        >
          <v-sheet
            class="d-flex flex-column ga-3 align-start pa-3 border"
            max-width="500"
            rounded="xl"
          >
            <v-btn
              :text="current.dark ? 'Dark' : 'Light'"
              prepend-icon="mdi-theme-light-dark"
              variant="tonal"
              rounded
              @click="$vuetify.theme.cycle()"
            />
            <span class="text-caption font-weight-medium">Primary</span>
            <v-item-group v-model="primaryColor" class="d-flex ga-2 flex-wrap" mandatory>
              <v-item
                v-for="[key, c] of swatchColors"
                :key="key"
                v-slot="{ isSelected, toggle }"
                :value="key"
              >
                <v-icon-btn
                  :color="c[current.dark ? 'lighten1' : 'darken1']"
                  :icon="isSelected ? '$complete' : ''"
                  @click="toggle"
                />
              </v-item>
            </v-item-group>
            <span class="text-caption font-weight-medium">Surface</span>
            <v-item-group v-model="surfaceColor" class="d-flex ga-2 flex-wrap" mandatory>
              <v-item
                v-for="[key, c] of Object.entries(surfaceColors)"
                :key="key"
                v-slot="{ isSelected, toggle }"
                :value="key"
              >
                <v-icon-btn
                  :color="c.base"
                  :icon="isSelected ? '$complete' : ''"
                  @click="toggle"
                />
              </v-item>
            </v-item-group>
          </v-sheet>
        </v-menu>
      </v-btn>
      <v-btn
        :text="`inset: ${inset || 'OFF'}`"
        variant="tonal"
        @click="inset = insets[(insets.indexOf(inset) + 1) % insets.length]"
      />
      <v-btn
        :text="`loading: ${loading ? 'ON' : 'OFF'}`"
        variant="tonal"
        @click="loading = !loading"
      />
      <v-btn
        :text="`density: ${density}`"
        variant="tonal"
        @click="density = densities[(densities.indexOf(density) + 1) % densities.length]"
      />
      <v-btn
        :text="`icons: ${icons ? 'ON' : 'OFF'}`"
        variant="tonal"
        @click="icons = !icons"
      />
    </div>
  </v-app>
</template>

<script setup>
  import { useTheme } from 'vuetify'
  import { ref, shallowRef, watch } from 'vue'
  import paletteColors from '../src/util/colors'

  const insets = [false, 'tonal', 'material', 'square']
  const inset = ref('material')

  const loading = ref(false)

  const densities = ['default', 'comfortable', 'compact']
  const density = ref('compact')

  const icons = ref(true)

  const sizes = ['x-small', 'small', 'default', 'large', 'x-large']

  const { themes, current, change } = useTheme()

  change('dark')

  const swatchColors = Object.entries(paletteColors).filter(([key]) => key !== 'shades')

  const primaryColor = shallowRef('deepPurple')
  watch(primaryColor, v => {
    themes.value.light.colors.primary = paletteColors[v].darken1
    themes.value.dark.colors.primary = paletteColors[v].lighten4
    themes.value.dark.colors['on-primary'] = paletteColors[v].darken3
  }, { immediate: true })

  const surfaceColors = {
    slate: { base: '#64748b', lighten: '#e2e8f0', darken: '#0f172a' },
    gray: { base: '#6b7280', lighten: '#e5e7eb', darken: '#111827' },
    zinc: { base: '#71717a', lighten: '#e4e4e7', darken: '#18181b' },
    neutral: { base: '#737373', lighten: '#e5e5e5', darken: '#171717' },
    stone: { base: '#78716c', lighten: '#e7e5e4', darken: '#1c1917' },
  }
  const surfaceColor = shallowRef('stone')
  watch(surfaceColor, v => {
    themes.value.light.colors.surface = surfaceColors[v].lighten
    themes.value.dark.colors.surface = surfaceColors[v].darken
  }, { immediate: true })

  // [color, thumbColor?]
  const colors = [
    ['red'],
    ['red-darken-3'],
    ['indigo'],
    ['indigo-darken-3'],
    ['orange-lighten-3', 'orange-darken-2'],
    ['orange-darken-3'],
    ['#64a'],
    ['#cf3'],
    ['success'],
    ['info'],
    ['warning'],
    ['error'],
  ]

  const model = ref(colors.map(([color]) => color))
</script>

@J-Sek J-Sek self-assigned this May 30, 2026
@J-Sek J-Sek added T: feature A new feature C: VSwitch labels May 30, 2026
@J-Sek J-Sek marked this pull request as ready for review May 30, 2026 23:15
@J-Sek J-Sek force-pushed the feat/vswitch-sizes branch from a243028 to dda9a7b Compare May 30, 2026 23:15
@J-Sek J-Sek merged commit d0fb972 into dev May 30, 2026
16 checks passed
@J-Sek J-Sek deleted the feat/vswitch-sizes branch May 30, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Change size of v-switch when density is change with attribute "inset"

1 participant