Skip to content

Commit 76ba11d

Browse files
authored
Settings ui fixes (#5352)
* Fix tabbed modal icon size * Fix slider input being unstyled * Refactor slider component to use ui components and tailwind * Pnpm fix my beloved --------- Co-authored-by: Creeperkatze <178587183+Creeperkatze@users.noreply.github.com>
1 parent f22e49e commit 76ba11d

File tree

2 files changed

+105
-163
lines changed

2 files changed

+105
-163
lines changed
Lines changed: 104 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,53 @@
11
<template>
2-
<div class="root-container">
3-
<div class="slider-component">
4-
<div class="slide-container">
5-
<div class="snap-points-wrapper">
6-
<div class="snap-points">
7-
<div
8-
v-for="snapPoint in snapPoints"
9-
:key="snapPoint"
10-
class="snap-point"
11-
:class="{ green: snapPoint <= currentValue, 'opacity-0': disabled }"
12-
:style="{ left: ((snapPoint - min) / (max - min)) * 100 + '%' }"
13-
></div>
14-
</div>
15-
</div>
16-
<input
17-
ref="input"
18-
v-model="currentValue"
19-
type="range"
20-
:min="min"
21-
:max="max"
22-
:step="step"
23-
class="slider"
24-
:class="{
25-
disabled: disabled,
26-
}"
27-
:disabled="disabled"
28-
:style="{
29-
'--current-value': currentValue,
30-
'--min-value': min,
31-
'--max-value': max,
32-
}"
33-
@input="onInputWithSnap(($event.target as HTMLInputElement).value)"
34-
/>
35-
<div class="slider-range">
36-
<span> {{ min }} {{ unit }} </span>
37-
<span> {{ max }} {{ unit }} </span>
2+
<div class="flex flex-row items-center w-full">
3+
<div class="w-full relative">
4+
<div class="absolute top-0 h-1/2 w-full">
5+
<div
6+
class="relative inline-block align-middle w-[calc(100%-0.75rem)] h-3 left-[calc(0.75rem/2)]"
7+
>
8+
<div
9+
v-for="snapPoint in snapPoints"
10+
:key="snapPoint"
11+
class="absolute inline-block w-1 h-full rounded-sm -translate-x-1/2"
12+
:class="{
13+
'opacity-0': disabled,
14+
}"
15+
:style="{
16+
left: ((snapPoint - min) / (max - min)) * 100 + '%',
17+
backgroundColor:
18+
snapPoint <= currentValue ? 'var(--color-brand)' : 'var(--color-base)',
19+
}"
20+
></div>
3821
</div>
3922
</div>
23+
<input
24+
ref="input"
25+
v-model="currentValue"
26+
type="range"
27+
:min="min"
28+
:max="max"
29+
:step="step"
30+
class="slider relative rounded-sm h-1 w-full p-0 min-h-0 shadow-none outline-none align-middle appearance-none"
31+
:class="{
32+
'opacity-50 cursor-not-allowed': disabled,
33+
}"
34+
:disabled="disabled"
35+
:style="{
36+
'--current-value': currentValue,
37+
'--min-value': min,
38+
'--max-value': max,
39+
}"
40+
@input="onInputWithSnap(($event.target as HTMLInputElement).value)"
41+
/>
42+
<div class="flex flex-row justify-between text-xs m-0">
43+
<span> {{ min }} {{ unit }} </span>
44+
<span> {{ max }} {{ unit }} </span>
45+
</div>
4046
</div>
41-
<input
42-
ref="value"
43-
:value="currentValue"
47+
<StyledInput
48+
:model-value="String(currentValue)"
4449
type="number"
45-
class="slider-input"
50+
class="w-24 ml-3"
4651
:disabled="disabled"
4752
:min="min"
4853
:max="max"
@@ -53,7 +58,9 @@
5358
</template>
5459

5560
<script setup lang="ts">
56-
import { ref } from 'vue'
61+
import { ref, watch } from 'vue'
62+
63+
import StyledInput from './StyledInput.vue'
5764
5865
const emit = defineEmits<{ 'update:modelValue': [number] }>()
5966
@@ -83,6 +90,13 @@ const props = withDefaults(defineProps<Props>(), {
8390
8491
const currentValue = ref(Math.max(props.min, props.modelValue))
8592
93+
watch(
94+
() => props.modelValue,
95+
(newValue) => {
96+
currentValue.value = Math.max(props.min, newValue ?? props.min)
97+
},
98+
)
99+
86100
const inputValueValid = (inputValue: number) => {
87101
let newValue = inputValue || props.min
88102
@@ -115,135 +129,63 @@ const onInput = (value: string) => {
115129
</script>
116130

117131
<style lang="scss" scoped>
118-
.root-container {
119-
--transition-speed: 0.2s;
120-
121-
@media (prefers-reduced-motion) {
122-
--transition-speed: 0s;
123-
}
124-
125-
display: flex;
126-
flex-direction: row;
127-
align-items: center;
128-
width: 100%;
129-
}
130-
131-
.slider-component,
132-
.slide-container {
133-
width: 100%;
134-
135-
position: relative;
136-
}
137-
138-
.slider-component .slide-container .slider {
132+
.slider {
139133
-webkit-appearance: none;
140134
appearance: none;
141-
position: relative;
142-
143-
border-radius: var(--radius-sm);
144-
height: 0.25rem;
145-
width: 100%;
146-
padding: 0;
147-
min-height: 0px;
148-
box-shadow: none;
149-
150135
background: linear-gradient(
151-
to right,
152-
var(--color-brand),
153-
var(--color-brand)
154-
calc((var(--current-value) - var(--min-value)) / (var(--max-value) - var(--min-value)) * 100%),
155-
var(--color-base)
156-
calc((var(--current-value) - var(--min-value)) / (var(--max-value) - var(--min-value)) * 100%),
157-
var(--color-base) 100%
158-
);
159-
background-size: 100% 100%;
160-
outline: none;
161-
vertical-align: middle;
162-
}
163-
164-
.slider-component .slide-container .slider::-webkit-slider-thumb {
165-
-webkit-appearance: none;
166-
appearance: none;
167-
width: 0.75rem;
168-
height: 0.75rem;
169-
background: var(--color-brand);
170-
cursor: pointer;
171-
border-radius: 50%;
172-
transition: var(--transition-speed);
173-
}
174-
175-
.slider-component .slide-container .slider::-moz-range-thumb {
176-
border: none;
177-
width: 0.75rem;
178-
height: 0.75rem;
179-
background: var(--color-brand);
180-
cursor: pointer;
181-
border-radius: 50%;
182-
transition: var(--transition-speed);
183-
}
184-
185-
.slider-component .slide-container .slider:hover::-webkit-slider-thumb:not(.disabled) {
186-
width: 1rem;
187-
height: 1rem;
188-
transition: var(--transition-speed);
189-
}
190-
191-
.slider-component .slide-container .slider:hover::-moz-range-thumb:not(.disabled) {
192-
width: 1rem;
193-
height: 1rem;
194-
transition: var(--transition-speed);
195-
}
196-
197-
.slider-component .slide-container .snap-points-wrapper {
198-
position: absolute;
199-
height: 50%;
200-
width: 100%;
201-
202-
.snap-points {
203-
position: relative;
204-
display: inline-block;
205-
206-
vertical-align: middle;
207-
208-
width: calc(100% - 0.75rem);
136+
to right,
137+
var(--color-brand) 0%,
138+
var(--color-brand)
139+
calc(
140+
(var(--current-value) - var(--min-value)) / (var(--max-value) - var(--min-value)) * 100%
141+
),
142+
var(--color-base)
143+
calc(
144+
(var(--current-value) - var(--min-value)) / (var(--max-value) - var(--min-value)) * 100%
145+
),
146+
var(--color-base) 100%
147+
)
148+
100% 100% no-repeat;
149+
150+
&::-webkit-slider-thumb {
151+
-webkit-appearance: none;
152+
appearance: none;
153+
width: 0.75rem;
209154
height: 0.75rem;
210-
211-
left: calc(0.75rem / 2);
212-
213-
.snap-point {
214-
position: absolute;
215-
display: inline-block;
216-
217-
width: 0.25rem;
218-
height: 100%;
219-
border-radius: var(--radius-sm);
220-
221-
background-color: var(--color-base);
222-
223-
transform: translateX(calc(-0.25rem / 2));
224-
225-
&.green {
226-
background-color: var(--color-brand);
227-
}
155+
background: var(--color-brand);
156+
border-radius: 50%;
157+
transition:
158+
width 0.2s,
159+
height 0.2s;
160+
161+
@media (prefers-reduced-motion: reduce) {
162+
transition: none;
228163
}
229164
}
230-
}
231165
232-
.slider-input {
233-
width: 6rem;
234-
margin-left: 0.75rem;
235-
}
166+
&::-moz-range-thumb {
167+
border: none;
168+
width: 0.75rem;
169+
height: 0.75rem;
170+
background: var(--color-brand);
171+
border-radius: 50%;
172+
transition:
173+
width 0.2s,
174+
height 0.2s;
175+
176+
@media (prefers-reduced-motion: reduce) {
177+
transition: none;
178+
}
179+
}
236180
237-
.slider-range {
238-
display: flex;
239-
flex-direction: row;
240-
justify-content: space-between;
241-
font-size: 0.75rem;
242-
margin: 0;
243-
}
181+
&:hover:not(:disabled)::-webkit-slider-thumb,
182+
&:hover:not(:disabled)::-moz-range-thumb {
183+
width: 1rem;
184+
height: 1rem;
185+
}
244186
245-
.disabled {
246-
opacity: 0.5;
247-
cursor: not-allowed;
187+
&:disabled {
188+
pointer-events: none;
189+
}
248190
}
249191
</style>

packages/ui/src/components/modal/TabbedModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ defineExpose({ selectedTab, setTab })
4343
:class="`flex gap-2 items-center text-left rounded-xl px-4 py-2 border-none text-nowrap font-semibold cursor-pointer active:scale-[0.97] transition-all ${selectedTab === index ? 'bg-button-bgSelected text-button-textSelected' : 'bg-transparent text-button-text hover:bg-button-bg hover:text-contrast'}`"
4444
@click="() => setTab(index)"
4545
>
46-
<component :is="tab.icon" class="w-4 h-4" />
46+
<component :is="tab.icon" class="w-4 h-4 flex-shrink-0" />
4747
<span>{{ formatMessage(tab.name) }}</span>
4848
<span
4949
v-if="tab.badge"

0 commit comments

Comments
 (0)