implement colour picker for profile icon
This commit is contained in:
32
package-lock.json
generated
32
package-lock.json
generated
@@ -24,7 +24,8 @@
|
||||
"vis-data": "^7.1.9",
|
||||
"vis-network": "^9.1.9",
|
||||
"vite": "^6.0.5",
|
||||
"vue-router": "^4.5.0"
|
||||
"vue-router": "^4.5.0",
|
||||
"vuetify": "^3.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^30.0.8",
|
||||
@@ -5731,6 +5732,35 @@
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vuetify": {
|
||||
"version": "3.7.6",
|
||||
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.6.tgz",
|
||||
"integrity": "sha512-lol0Va5HtMIqZfjccSD5DLv5v31R/asJXzc6s7ULy51PHr1DjXxWylZejhq0kVpMGW64MiV1FmA/p8eYQfOWfQ==",
|
||||
"engines": {
|
||||
"node": "^12.20 || >=14.13"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/johnleider"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.7",
|
||||
"vite-plugin-vuetify": ">=1.0.0",
|
||||
"vue": "^3.3.0",
|
||||
"webpack-plugin-vuetify": ">=2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
},
|
||||
"vite-plugin-vuetify": {
|
||||
"optional": true
|
||||
},
|
||||
"webpack-plugin-vuetify": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"vis-data": "^7.1.9",
|
||||
"vis-network": "^9.1.9",
|
||||
"vite": "^6.0.5",
|
||||
"vue-router": "^4.5.0"
|
||||
"vue-router": "^4.5.0",
|
||||
"vuetify": "^3.7.6"
|
||||
}
|
||||
}
|
||||
|
||||
91
src/frontend/components/ColourPickerDropdown.vue
Normal file
91
src/frontend/components/ColourPickerDropdown.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div v-click-outside="{ handler: onClickOutsideMenu, capture: true }" class="cursor-default relative inline-block text-left">
|
||||
|
||||
<!-- menu button -->
|
||||
<div ref="dropdown-button" @click.stop="toggleMenu">
|
||||
<slot>
|
||||
<div class="size-8 border border-gray-50 rounded shadow cursor-pointer" :style="{ 'background-color': colour }"></div>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<!-- drop down menu -->
|
||||
<Transition
|
||||
enter-active-class="transition ease-out duration-100"
|
||||
enter-from-class="transform opacity-0 scale-95"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-75"
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95">
|
||||
<div v-if="isShowingMenu" class="absolute left-0 z-10 ml-4">
|
||||
<v-color-picker v-model="colourPickerValue" :modes="['hex']" hide-inputs hide-sliders show-swatches></v-color-picker>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DropDownMenu from "./DropDownMenu.vue";
|
||||
import IconButton from "./IconButton.vue";
|
||||
|
||||
export default {
|
||||
name: 'ColourPickerDropdown',
|
||||
components: {
|
||||
IconButton,
|
||||
DropDownMenu,
|
||||
},
|
||||
emits: [
|
||||
'update:colour',
|
||||
],
|
||||
props: {
|
||||
colour: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowingMenu: false,
|
||||
colourPickerValue: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggleMenu() {
|
||||
if(this.isShowingMenu){
|
||||
this.hideMenu();
|
||||
} else {
|
||||
this.showMenu();
|
||||
}
|
||||
},
|
||||
showMenu() {
|
||||
this.isShowingMenu = true;
|
||||
},
|
||||
hideMenu() {
|
||||
this.isShowingMenu = false;
|
||||
},
|
||||
onClickOutsideMenu(event) {
|
||||
if(this.isShowingMenu){
|
||||
event.preventDefault();
|
||||
this.hideMenu();
|
||||
}
|
||||
},
|
||||
},
|
||||
watch:{
|
||||
colour() {
|
||||
// update internal colour picker value when parent changes value of v-model:colour
|
||||
this.colourPickerValue = this.colour;
|
||||
},
|
||||
colourPickerValue() {
|
||||
|
||||
// get current colour picker value
|
||||
var value = this.colourPickerValue;
|
||||
|
||||
// remove alpha channel from hex colour if present
|
||||
if(value.length === 9){
|
||||
value = value.substring(0, 7);
|
||||
}
|
||||
|
||||
// fire v-model:colour update event
|
||||
this.$emit("update:colour", value);
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -20,75 +20,21 @@
|
||||
<!-- colours -->
|
||||
<div class="bg-white dark:bg-zinc-800 rounded shadow">
|
||||
<div class="flex border-b border-gray-300 dark:border-zinc-700 text-gray-700 dark:text-gray-200 p-2 font-semibold">Select your Colours</div>
|
||||
<div class="divide-y divide-gray-300 dark:divide-zinc-700 text-gray-900 dark:text-gray-100">
|
||||
<div class="flex p-2 space-x-2">
|
||||
|
||||
<!-- icon colour -->
|
||||
<div class="p-2">
|
||||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Icon Colour</div>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Icon</div>
|
||||
<div class="flex">
|
||||
<select v-model="iconForegroundColour" class="bg-gray-50 dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 text-gray-900 dark:text-gray-100 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-600 dark:focus:border-blue-600 block w-full p-2.5">
|
||||
<option value="#000000">Black</option>
|
||||
<option value="#FFFFFF">White</option>
|
||||
<option disabled></option>
|
||||
<option value="#64748b">Slate</option>
|
||||
<option value="#6b7280">Gray</option>
|
||||
<option value="#71717a">Zinc</option>
|
||||
<option value="#737373">Neutral</option>
|
||||
<option value="#78716c">Stone</option>
|
||||
<option disabled></option>
|
||||
<option value="#ef4444">Red</option>
|
||||
<option value="#f97316">Orange</option>
|
||||
<option value="#f59e0b">Amber</option>
|
||||
<option value="#eab308">Yellow</option>
|
||||
<option value="#84cc16">Lime</option>
|
||||
<option value="#22c55e">Green</option>
|
||||
<option value="#10b981">Emerald</option>
|
||||
<option value="#14b8a6">Teal</option>
|
||||
<option value="#06b6d4">Cyan</option>
|
||||
<option value="#0ea5e9">Sky</option>
|
||||
<option value="#3b82f6">Blue</option>
|
||||
<option value="#6366f1">Indigo</option>
|
||||
<option value="#8b5cf6">Violet</option>
|
||||
<option value="#a855f7">Purple</option>
|
||||
<option value="#d946ef">Fuschia</option>
|
||||
<option value="#ec4899">Pink</option>
|
||||
<option value="#f43f5e">Rose</option>
|
||||
</select>
|
||||
<ColourPickerDropdown v-model:colour="iconForegroundColour"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- background colour -->
|
||||
<div class="p-2">
|
||||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Background Colour</div>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Background</div>
|
||||
<div class="flex">
|
||||
<select v-model="iconBackgroundColour" class="bg-gray-50 dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 text-gray-900 dark:text-gray-100 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-600 dark:focus:border-blue-600 block w-full p-2.5">
|
||||
<option value="#000000">Black</option>
|
||||
<option value="#FFFFFF">White</option>
|
||||
<option disabled></option>
|
||||
<option value="#64748b">Slate</option>
|
||||
<option value="#6b7280">Gray</option>
|
||||
<option value="#71717a">Zinc</option>
|
||||
<option value="#737373">Neutral</option>
|
||||
<option value="#78716c">Stone</option>
|
||||
<option disabled></option>
|
||||
<option value="#ef4444">Red</option>
|
||||
<option value="#f97316">Orange</option>
|
||||
<option value="#f59e0b">Amber</option>
|
||||
<option value="#eab308">Yellow</option>
|
||||
<option value="#84cc16">Lime</option>
|
||||
<option value="#22c55e">Green</option>
|
||||
<option value="#10b981">Emerald</option>
|
||||
<option value="#14b8a6">Teal</option>
|
||||
<option value="#06b6d4">Cyan</option>
|
||||
<option value="#0ea5e9">Sky</option>
|
||||
<option value="#3b82f6">Blue</option>
|
||||
<option value="#6366f1">Indigo</option>
|
||||
<option value="#8b5cf6">Violet</option>
|
||||
<option value="#a855f7">Purple</option>
|
||||
<option value="#d946ef">Fuschia</option>
|
||||
<option value="#ec4899">Pink</option>
|
||||
<option value="#f43f5e">Rose</option>
|
||||
</select>
|
||||
<ColourPickerDropdown v-model:colour="iconBackgroundColour"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -124,9 +70,12 @@ import * as mdi from "@mdi/js";
|
||||
import MaterialDesignIcon from "../../../../build/exe/lib/src/frontend/components/MaterialDesignIcon.vue";
|
||||
import LxmfUserIcon from "../LxmfUserIcon.vue";
|
||||
import DialogUtils from "../../js/DialogUtils";
|
||||
import ColourPickerDropdown from "../ColourPickerDropdown.vue";
|
||||
|
||||
export default {
|
||||
name: 'ProfilePage',
|
||||
components: {
|
||||
ColourPickerDropdown,
|
||||
LxmfUserIcon,
|
||||
MaterialDesignIcon,
|
||||
},
|
||||
|
||||
@@ -7,6 +7,16 @@ import "./fonts/RobotoMonoNerdFont/font.css";
|
||||
|
||||
import App from './components/App.vue';
|
||||
|
||||
// init vuetify
|
||||
import 'vuetify/styles';
|
||||
import { createVuetify } from 'vuetify';
|
||||
import * as components from 'vuetify/components';
|
||||
import * as directives from 'vuetify/directives';
|
||||
const vuetify = createVuetify({
|
||||
components,
|
||||
directives,
|
||||
})
|
||||
|
||||
// provide axios globally
|
||||
window.axios = axios;
|
||||
|
||||
@@ -85,5 +95,6 @@ const router = createRouter({
|
||||
|
||||
createApp(App)
|
||||
.use(router)
|
||||
.use(vuetify)
|
||||
.use(vClickOutside)
|
||||
.mount('#app');
|
||||
|
||||
Reference in New Issue
Block a user