/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2023 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import "./Switch.css"; import { classNameFactory } from "@utils/css"; import { useState } from "@webpack/common"; import type { FocusEvent, Ref } from "react"; const switchCls = classNameFactory("vc-switch-"); export interface SwitchProps { checked: boolean; onChange: (checked: boolean) => void; disabled?: boolean; id?: string; // checkmark/x icon in thumb hasIcon?: boolean; innerRef?: Ref; "aria-describedby"?: string; "aria-labelledby"?: string; } export function Switch({ checked, onChange, disabled, id, hasIcon = false, innerRef, ...ariaProps }: SwitchProps) { const [focusVisible, setFocusVisible] = useState(false); // Due to how we wrap the invisible input, there is no good way to do this with css. // We need it on the parent, not the input itself. For this, you can use either: // - :focus-within ~ this shows also when clicking, not just on keyboard focus => SUCKS // - :has(:focus-visible) ~ works but :has performs terribly inside Discord // - JS event handlers ~ what we are using now const handleFocusChange = (event: FocusEvent) => { const target = event.currentTarget; setFocusVisible(target.matches(":focus-visible")); }; return ( ); }