slider: design
This commit is contained in:
38
README.md
38
README.md
@@ -1,39 +1,3 @@
|
|||||||
# batu-ui
|
# batu-ui
|
||||||
|
|
||||||
This template should help get you started developing with Vue 3 in Vite.
|
A UI for a random project...
|
||||||
|
|
||||||
## Recommended IDE Setup
|
|
||||||
|
|
||||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
||||||
|
|
||||||
## Type Support for `.vue` Imports in TS
|
|
||||||
|
|
||||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
||||||
|
|
||||||
## Customize configuration
|
|
||||||
|
|
||||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
||||||
|
|
||||||
## Project Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compile and Hot-Reload for Development
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type-Check, Compile and Minify for Production
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint with [ESLint](https://eslint.org/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
27
src/App.vue
27
src/App.vue
@@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
* libreevent - App.vue
|
* batu-ui - App.vue
|
||||||
*
|
*
|
||||||
* Created by Janis Hutz 05/14/2023, Licensed under the GPL V3 License
|
* Created by Janis Hutz 09/30/2024, Licensed under the GPL V3 License
|
||||||
* https://janishutz.com, development@janishutz.com
|
* https://janishutz.com, development@janishutz.com
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import stopSlider from './components/stopSlider.vue';
|
||||||
|
|
||||||
const theme = ref( 'light_mode' );
|
const theme = ref( 'light_mode' );
|
||||||
|
|
||||||
@@ -76,6 +77,12 @@
|
|||||||
alert( 'Error logging in. Please retry!' )
|
alert( 'Error logging in. Please retry!' )
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyDownHandler = ( e: KeyboardEvent ) => {
|
||||||
|
if ( e.key === 'Enter' ) {
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -83,19 +90,27 @@
|
|||||||
<button @click="changeTheme();" id="themeSelector" title="Toggle between light and dark mode"><span class="material-symbols-outlined" v-html="theme"></span></button>
|
<button @click="changeTheme();" id="themeSelector" title="Toggle between light and dark mode"><span class="material-symbols-outlined" v-html="theme"></span></button>
|
||||||
<main>
|
<main>
|
||||||
<h1>Smoke Data Recorder</h1>
|
<h1>Smoke Data Recorder</h1>
|
||||||
<div v-if="unlocked"></div>
|
<div v-if="!isLoading">
|
||||||
|
<div v-if="unlocked">
|
||||||
|
<input type="text" class="input" placeholder="">
|
||||||
|
<stopSlider id="test" style="width: 80vw; margin-left: 20px;"></stopSlider>
|
||||||
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p>Please log in</p>
|
<p>Please log in</p>
|
||||||
<div v-if="!showPW">
|
<div v-if="!showPW">
|
||||||
<input type="password" placeholder="Password" class="input" v-model="pw">
|
<input type="password" placeholder="Password" class="input" v-model="pw" @keydown="( e ) => keyDownHandler( e )">
|
||||||
<button class="transparent-button" @click="togglePWShow()"><span class="material-symbols-outlined">visibility</span></button><br>
|
<button class="transparent-button" @click="togglePWShow()"><span class="material-symbols-outlined">visibility</span></button><br>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<input type="text" placeholder="Password" class="input" v-model="pw">
|
<input type="text" placeholder="Password" class="input" v-model="pw" @keydown="( e ) => keyDownHandler( e )">
|
||||||
<button class="transparent-button" @click="togglePWShow()"><span class="material-symbols-outlined">visibility_off</span></button><br>
|
<button class="transparent-button" @click="togglePWShow()"><span class="material-symbols-outlined">visibility_off</span></button><br>
|
||||||
</div>
|
</div>
|
||||||
<button @click="unlock()" class="fancy-button" style="margin-top: 10px;">Login</button>
|
<button @click="unlock()" class="fancy-button" style="margin-top: 10px;">Login</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -168,7 +183,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
transition: 0.5s;
|
transition: all 0.5s;
|
||||||
background-color: var( --background-color );
|
background-color: var( --background-color );
|
||||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||||
/* font-family: Avenir, Helvetica, Arial, sans-serif; */
|
/* font-family: Avenir, Helvetica, Arial, sans-serif; */
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<template>
|
<!--
|
||||||
<div>
|
* batu-ui - stopSlider.vue
|
||||||
<div class="slider-knob"></div>
|
*
|
||||||
<div class="slider">
|
* Created by Janis Hutz 09/30/2024, Licensed under the GPL V3 License
|
||||||
<div class="slider-fill" :style="'right: ' + sliderFillPosLeft + 'px; width: ' + ( maxWidth - sliderFillPosLeft - sliderFillPosRight ) + 'px'"></div>
|
* https://janishutz.com, development@janishutz.com
|
||||||
<div class="slider-stop" v-for="stop in sliderStops" v-bind:key="stop.index" :style="'left: ' + stop.x + 'px;'"></div>
|
*
|
||||||
</div>
|
*
|
||||||
</div>
|
-->
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -18,7 +17,99 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const maxWidth = ref( window.innerWidth ); // TODO: Update to reflect slider width
|
const maxWidth = ref( window.innerWidth ); // TODO: Update to reflect slider width
|
||||||
const sliderFillPosLeft = ref( 0 ); // Offset from left edge
|
const sliderFillPosLeft = ref( -11 ); // Offset from left edge
|
||||||
const sliderFillPosRight = ref( 0 ); // Offset from right edge
|
const sliderFillPosRight = ref( 0 ); // Offset from right edge
|
||||||
const sliderStops: Ref<SliderStop[]> = ref( [] );
|
const sliderStops: Ref<SliderStop[]> = ref( [] );
|
||||||
|
|
||||||
|
const setUp = ( stops: number ) => {
|
||||||
|
maxWidth.value = document.getElementById( 'slider-' + props.id )!.clientWidth;
|
||||||
|
sliderStops.value = [];
|
||||||
|
const intervalSize = maxWidth.value / ( stops - 1 );
|
||||||
|
for ( let i = 0; i < stops; i ++ ) {
|
||||||
|
sliderStops.value.push( {
|
||||||
|
x: intervalSize * i - 10,
|
||||||
|
index: i,
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps( {
|
||||||
|
'id': {
|
||||||
|
default: '1',
|
||||||
|
required: true,
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
defineExpose( {
|
||||||
|
setUp
|
||||||
|
} );
|
||||||
|
|
||||||
|
setTimeout( () => {
|
||||||
|
setUp( 5 );
|
||||||
|
}, 500 );
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="slider-container">
|
||||||
|
<div class="slider-knob" :style="'left: ' + sliderFillPosLeft + 'px;'"></div>
|
||||||
|
<div class="slider-stop" v-for="stop in sliderStops" v-bind:key="stop.index" :style="'left: ' + stop.x + 'px;'"></div>
|
||||||
|
<div class="slider" :id="'slider-' + $props.id">
|
||||||
|
<div class="slider-fill" :style="'left: ' + sliderFillPosLeft + 'px; width: ' + ( maxWidth - sliderFillPosLeft - sliderFillPosRight ) + 'px'"></div>
|
||||||
|
<div class="slider-stop-fill" v-for="stop in sliderStops" v-bind:key="stop.index" :style="'left: ' + stop.x + 'px;'"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.slider-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-knob {
|
||||||
|
background-color: var( --slider-color );
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
border-radius: 15px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5;
|
||||||
|
top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
width: 100%;
|
||||||
|
height: 10px;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 15px;
|
||||||
|
z-index: 2;
|
||||||
|
border: 2px var( --gray-color ) solid;
|
||||||
|
background-color: var( --background-color );
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-fill {
|
||||||
|
height: 5px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-stop {
|
||||||
|
border-radius: 10px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: solid 2px var( --gray-color );
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-stop-fill {
|
||||||
|
border-radius: 10px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
background-color: var( --background-color );
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user