mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-21 15:31:46 +01:00
feat(module): implement --ui-radius CSS variable (#2341)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
140
docs/app/components/theme-picker/ThemePicker.vue
Normal file
140
docs/app/components/theme-picker/ThemePicker.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<UPopover :ui="{ content: 'w-72 px-6 py-4 flex flex-col gap-4' }">
|
||||
<template #default="{ open }">
|
||||
<UButton
|
||||
icon="i-heroicons-swatch"
|
||||
color="neutral"
|
||||
:variant="open ? 'soft' : 'ghost'"
|
||||
square
|
||||
aria-label="Color picker"
|
||||
:ui="{ leadingIcon: 'text-[--ui-primary]' }"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<fieldset>
|
||||
<legend class="text-[11px] leading-none font-semibold mb-2">
|
||||
Primary
|
||||
</legend>
|
||||
|
||||
<div class="grid grid-cols-3 gap-1 -mx-2">
|
||||
<ThemePickerButton
|
||||
v-for="color in primaryColors"
|
||||
:key="color"
|
||||
:label="color"
|
||||
:chip="color"
|
||||
:selected="primary === color"
|
||||
@select="primary = color"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend class="text-[11px] leading-none font-semibold mb-2">
|
||||
Neutral
|
||||
</legend>
|
||||
|
||||
<div class="grid grid-cols-3 gap-1 -mx-2">
|
||||
<ThemePickerButton
|
||||
v-for="color in neutralColors"
|
||||
:key="color"
|
||||
:label="color"
|
||||
:chip="color"
|
||||
:selected="neutral === color"
|
||||
@select="neutral = color"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend class="text-[11px] leading-none font-semibold mb-2">
|
||||
Radius
|
||||
</legend>
|
||||
|
||||
<div class="grid grid-cols-5 gap-1 -mx-2">
|
||||
<ThemePickerButton
|
||||
v-for="r in radiuses"
|
||||
:key="r"
|
||||
:label="String(r)"
|
||||
class="justify-center px-0"
|
||||
:selected="radius === r"
|
||||
@select="radius = r"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend class="text-[11px] leading-none font-semibold mb-2">
|
||||
Theme
|
||||
</legend>
|
||||
|
||||
<div class="flex gap-1 -mx-2">
|
||||
<ThemePickerButton
|
||||
v-for="m in modes"
|
||||
:key="m.label"
|
||||
v-bind="m"
|
||||
:selected="mode === m.label"
|
||||
@select="mode = m.label"
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import colors from 'tailwindcss/colors'
|
||||
import { omit } from '#ui/utils'
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
// Computed
|
||||
|
||||
const neutralColors = ['slate', 'gray', 'zinc', 'neutral', 'stone']
|
||||
const neutral = computed({
|
||||
get() {
|
||||
return appConfig.ui.colors.neutral
|
||||
},
|
||||
set(option) {
|
||||
appConfig.ui.colors.neutral = option
|
||||
window.localStorage.setItem('nuxt-ui-neutral', appConfig.ui.colors.neutral)
|
||||
}
|
||||
})
|
||||
|
||||
const colorsToOmit = ['inherit', 'current', 'transparent', 'black', 'white', ...neutralColors]
|
||||
const primaryColors = Object.keys(omit(colors, colorsToOmit as any))
|
||||
const primary = computed({
|
||||
get() {
|
||||
return appConfig.ui.colors.primary
|
||||
},
|
||||
set(option) {
|
||||
appConfig.ui.colors.primary = option
|
||||
window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.colors.primary)
|
||||
}
|
||||
})
|
||||
|
||||
const radiuses = [0, 0.125, 0.25, 0.375, 0.5]
|
||||
const radius = computed({
|
||||
get() {
|
||||
return appConfig.theme.radius
|
||||
},
|
||||
set(option) {
|
||||
appConfig.theme.radius = option
|
||||
window.localStorage.setItem('nuxt-ui-radius', String(appConfig.theme.radius))
|
||||
}
|
||||
})
|
||||
|
||||
const modes = [
|
||||
{ label: 'light', icon: appConfig.ui.icons.light },
|
||||
{ label: 'dark', icon: appConfig.ui.icons.dark }
|
||||
]
|
||||
const mode = computed({
|
||||
get() {
|
||||
return colorMode.value
|
||||
},
|
||||
set(option) {
|
||||
colorMode.preference = option
|
||||
}
|
||||
})
|
||||
</script>
|
||||
32
docs/app/components/theme-picker/ThemePickerButton.vue
Normal file
32
docs/app/components/theme-picker/ThemePickerButton.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<UButton
|
||||
size="sm"
|
||||
color="neutral"
|
||||
:icon="icon"
|
||||
:label="label"
|
||||
:variant="selected ? 'soft' : 'outline'"
|
||||
class="capitalize ring-[--ui-border] rounded-[--ui-radius] text-[11px]"
|
||||
@click.stop.prevent="$emit('select')"
|
||||
>
|
||||
<template v-if="chip" #leading>
|
||||
<span
|
||||
class="inline-block w-2 h-2 rounded-full"
|
||||
:class="`bg-[--color-light] dark:bg-[--color-dark]`"
|
||||
:style="{
|
||||
'--color-light': `var(--color-${chip}-500)`,
|
||||
'--color-dark': `var(--color-${chip}-400)`
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
label: string
|
||||
icon?: string
|
||||
chip?: string
|
||||
selected?: boolean
|
||||
}>()
|
||||
defineEmits(['select'])
|
||||
</script>
|
||||
Reference in New Issue
Block a user