mirror of
https://github.com/wukko/cobalt.git
synced 2025-05-20 15:17:07 +02:00
web: add haptics to toggles & switchers
This commit is contained in:
parent
66401c6c5f
commit
6b09bd4688
@ -6,6 +6,8 @@
|
|||||||
Value extends CobaltSettings[Context][Id]
|
Value extends CobaltSettings[Context][Id]
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
import { hapticSwitch } from "$lib/haptics";
|
||||||
|
|
||||||
import settings, { updateSetting } from "$lib/state/settings";
|
import settings, { updateSetting } from "$lib/state/settings";
|
||||||
import type { CobaltSettings } from "$lib/types/settings";
|
import type { CobaltSettings } from "$lib/types/settings";
|
||||||
|
|
||||||
@ -22,12 +24,14 @@
|
|||||||
class="button"
|
class="button"
|
||||||
class:active={isActive}
|
class:active={isActive}
|
||||||
aria-pressed={isActive}
|
aria-pressed={isActive}
|
||||||
on:click={() =>
|
on:click={() => {
|
||||||
|
hapticSwitch();
|
||||||
updateSetting({
|
updateSetting({
|
||||||
[settingContext]: {
|
[settingContext]: {
|
||||||
[settingId]: settingValue,
|
[settingId]: settingValue,
|
||||||
},
|
},
|
||||||
})}
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</button>
|
</button>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
Id extends keyof CobaltSettings[Context]
|
Id extends keyof CobaltSettings[Context]
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
import { hapticSwitch } from "$lib/haptics";
|
||||||
import settings, { updateSetting } from "$lib/state/settings";
|
import settings, { updateSetting } from "$lib/state/settings";
|
||||||
import type { CobaltSettings } from "$lib/types/settings";
|
import type { CobaltSettings } from "$lib/types/settings";
|
||||||
|
|
||||||
@ -34,14 +35,15 @@
|
|||||||
class="button toggle-container"
|
class="button toggle-container"
|
||||||
role="switch"
|
role="switch"
|
||||||
aria-checked={isEnabled}
|
aria-checked={isEnabled}
|
||||||
disabled={disabled}
|
{disabled}
|
||||||
on:click={() =>
|
on:click={() => {
|
||||||
|
hapticSwitch();
|
||||||
updateSetting({
|
updateSetting({
|
||||||
[settingContext]: {
|
[settingContext]: {
|
||||||
[settingId]: !isEnabled,
|
[settingId]: !isEnabled,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<h4 class="toggle-title">{title}</h4>
|
<h4 class="toggle-title">{title}</h4>
|
||||||
<Toggle enabled={isEnabled} />
|
<Toggle enabled={isEnabled} />
|
||||||
@ -82,10 +84,14 @@
|
|||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
|
||||||
transition: background 0.1s, box-shadow 0.1s;
|
transition:
|
||||||
|
background 0.1s,
|
||||||
|
box-shadow 0.1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-container:active {
|
.toggle-container:active {
|
||||||
box-shadow: var(--button-box-shadow), 0 0 0 1.5px var(--button-stroke) inset;
|
box-shadow:
|
||||||
|
var(--button-box-shadow),
|
||||||
|
0 0 0 1.5px var(--button-stroke) inset;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -11,6 +11,7 @@ const device = {
|
|||||||
iPhone: false,
|
iPhone: false,
|
||||||
iPad: false,
|
iPad: false,
|
||||||
iOS: false,
|
iOS: false,
|
||||||
|
modernIOS: false,
|
||||||
android: false,
|
android: false,
|
||||||
mobile: false,
|
mobile: false,
|
||||||
},
|
},
|
||||||
@ -35,6 +36,9 @@ if (browser) {
|
|||||||
const iPhone = ua.includes("iphone os");
|
const iPhone = ua.includes("iphone os");
|
||||||
const iPad = !iPhone && ua.includes("mac os") && navigator.maxTouchPoints > 0;
|
const iPad = !iPhone && ua.includes("mac os") && navigator.maxTouchPoints > 0;
|
||||||
|
|
||||||
|
const iosVersion = Number(ua.match(/iphone os (\d+)_/)?.[1]);
|
||||||
|
const modernIOS = iPhone && iosVersion >= 18;
|
||||||
|
|
||||||
const iOS = iPhone || iPad;
|
const iOS = iPhone || iPad;
|
||||||
const android = ua.includes("android") || ua.includes("diordna");
|
const android = ua.includes("android") || ua.includes("diordna");
|
||||||
|
|
||||||
@ -45,11 +49,13 @@ if (browser) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
device.is = {
|
device.is = {
|
||||||
|
mobile: iOS || android,
|
||||||
|
android,
|
||||||
|
|
||||||
iPhone,
|
iPhone,
|
||||||
iPad,
|
iPad,
|
||||||
iOS,
|
iOS,
|
||||||
android,
|
modernIOS,
|
||||||
mobile: iOS || android,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
device.browser = {
|
device.browser = {
|
||||||
|
26
web/src/lib/haptics.ts
Normal file
26
web/src/lib/haptics.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { device } from "$lib/device";
|
||||||
|
|
||||||
|
// not sure if vibrations feel the same on android,
|
||||||
|
// so they're enabled only on ios 18+ for now
|
||||||
|
const shouldVibrate = device.is.modernIOS;
|
||||||
|
|
||||||
|
export const hapticSwitch = () => {
|
||||||
|
if (!shouldVibrate) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.ariaHidden = "true";
|
||||||
|
label.style.display = "none";
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.setAttribute("switch", "");
|
||||||
|
label.appendChild(input);
|
||||||
|
|
||||||
|
document.head.appendChild(label);
|
||||||
|
label.click();
|
||||||
|
document.head.removeChild(label);
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user