feat(@ui): migrate checkbox component

This commit is contained in:
Paul Makles 2022-05-29 16:34:54 +01:00
parent 20d31babce
commit 4bcfa601a5
18 changed files with 239 additions and 361 deletions

View file

@ -162,5 +162,8 @@
"repository": "https://github.com/revoltchat/revite.git", "repository": "https://github.com/revoltchat/revite.git",
"author": "Paul <paulmakles@gmail.com>", "author": "Paul <paulmakles@gmail.com>",
"license": "MIT", "license": "MIT",
"packageManager": "yarn@3.2.0" "packageManager": "yarn@3.2.0",
"resolutions": {
"@revoltchat/ui": "portal:../components"
}
} }

View file

@ -6,13 +6,11 @@ import styled from "styled-components/macro";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useState } from "preact/hooks"; import { useState } from "preact/hooks";
import { Button } from "@revoltchat/ui"; import { Button, Checkbox } from "@revoltchat/ui";
import { useApplicationState } from "../../mobx/State"; import { useApplicationState } from "../../mobx/State";
import { SECTION_NSFW } from "../../mobx/stores/Layout"; import { SECTION_NSFW } from "../../mobx/stores/Layout";
import Checkbox from "../ui/Checkbox";
import { Children } from "../../types/Preact"; import { Children } from "../../types/Preact";
const Base = styled.div` const Base = styled.div`
@ -81,10 +79,10 @@ export default observer((props: Props) => {
</span> </span>
<Checkbox <Checkbox
checked={layout.getSectionState(SECTION_NSFW, false)} title={<Text id="app.main.channel.nsfw.confirm" />}
onChange={() => layout.toggleSectionState(SECTION_NSFW, false)}> value={layout.getSectionState(SECTION_NSFW, false)}
<Text id="app.main.channel.nsfw.confirm" /> onChange={() => layout.toggleSectionState(SECTION_NSFW, false)}
</Checkbox> />
<div className="actions"> <div className="actions">
<Button palette="secondary" onClick={() => history.goBack()}> <Button palette="secondary" onClick={() => history.goBack()}>
<Text id="app.special.modals.actions.back" /> <Text id="app.special.modals.actions.back" />

View file

@ -1,11 +1,11 @@
import { User } from "revolt.js"; import { User } from "revolt.js";
import Checkbox, { CheckboxProps } from "../../ui/Checkbox"; import { Checkbox } from "@revoltchat/ui";
import UserIcon from "./UserIcon"; import UserIcon from "./UserIcon";
import { Username } from "./UserShort"; import { Username } from "./UserShort";
type UserProps = Omit<CheckboxProps, "children"> & { user: User }; type UserProps = { value: boolean; onChange: (v: boolean) => void; user: User };
export default function UserCheckbox({ user, ...props }: UserProps) { export default function UserCheckbox({ user, ...props }: UserProps) {
return ( return (

View file

@ -6,6 +6,8 @@ import pSBC from "shade-blend-color";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { Checkbox } from "@revoltchat/ui";
import TextAreaAutoSize from "../../lib/TextAreaAutoSize"; import TextAreaAutoSize from "../../lib/TextAreaAutoSize";
import { useApplicationState } from "../../mobx/State"; import { useApplicationState } from "../../mobx/State";
@ -19,12 +21,10 @@ import {
MONOSPACE_FONT_KEYS, MONOSPACE_FONT_KEYS,
} from "../../context/Theme"; } from "../../context/Theme";
import Checkbox from "../ui/Checkbox";
import ColourSwatches from "../ui/ColourSwatches"; import ColourSwatches from "../ui/ColourSwatches";
import ComboBox from "../ui/ComboBox"; import ComboBox from "../ui/ComboBox";
import Radio from "../ui/Radio"; import Radio from "../ui/Radio";
import CategoryButton from "../ui/fluent/CategoryButton"; import CategoryButton from "../ui/fluent/CategoryButton";
import { EmojiSelector } from "./appearance/EmojiSelector"; import { EmojiSelector } from "./appearance/EmojiSelector";
import { ThemeBaseSelector } from "./appearance/ThemeBaseSelector"; import { ThemeBaseSelector } from "./appearance/ThemeBaseSelector";
@ -200,13 +200,13 @@ export const DisplayLigaturesShim = observer(() => {
return ( return (
<> <>
<Checkbox <Checkbox
checked={settings.get("appearance:ligatures") ?? false} value={settings.get("appearance:ligatures") ?? false}
onChange={(v) => settings.set("appearance:ligatures", v)} onChange={(v) => settings.set("appearance:ligatures", v)}
title={<Text id="app.settings.pages.appearance.ligatures" />}
description={ description={
<Text id="app.settings.pages.appearance.ligatures_desc" /> <Text id="app.settings.pages.appearance.ligatures_desc" />
}> }
<Text id="app.settings.pages.appearance.ligatures" /> />
</Checkbox>
</> </>
); );
}); });
@ -219,13 +219,15 @@ export const ShowSendButtonShim = observer(() => {
return ( return (
<Checkbox <Checkbox
checked={settings.get("appearance:show_send_button") ?? false} value={settings.get("appearance:show_send_button") ?? false}
onChange={(v) => settings.set("appearance:show_send_button", v)} onChange={(v) => settings.set("appearance:show_send_button", v)}
title={
<Text id="app.settings.pages.appearance.appearance_options.show_send" />
}
description={ description={
<Text id="app.settings.pages.appearance.appearance_options.show_send_desc" /> <Text id="app.settings.pages.appearance.appearance_options.show_send_desc" />
}> }
<Text id="app.settings.pages.appearance.appearance_options.show_send" /> />
</Checkbox>
); );
}); });
@ -237,13 +239,15 @@ export const DisplaySeasonalShim = observer(() => {
return ( return (
<Checkbox <Checkbox
checked={settings.get("appearance:seasonal") ?? true} value={settings.get("appearance:seasonal") ?? true}
onChange={(v) => settings.set("appearance:seasonal", v)} onChange={(v) => settings.set("appearance:seasonal", v)}
title={
<Text id="app.settings.pages.appearance.theme_options.seasonal" />
}
description={ description={
<Text id="app.settings.pages.appearance.theme_options.seasonal_desc" /> <Text id="app.settings.pages.appearance.theme_options.seasonal_desc" />
}> }
<Text id="app.settings.pages.appearance.theme_options.seasonal" /> />
</Checkbox>
); );
}); });
@ -255,13 +259,15 @@ export const DisplayTransparencyShim = observer(() => {
return ( return (
<Checkbox <Checkbox
checked={settings.get("appearance:transparency") ?? true} value={settings.get("appearance:transparency") ?? true}
onChange={(v) => settings.set("appearance:transparency", v)} onChange={(v) => settings.set("appearance:transparency", v)}
title={
<Text id="app.settings.pages.appearance.theme_options.transparency" />
}
description={ description={
<Text id="app.settings.pages.appearance.theme_options.transparency_desc" /> <Text id="app.settings.pages.appearance.theme_options.transparency_desc" />
}> }
<Text id="app.settings.pages.appearance.theme_options.transparency" /> />
</Checkbox>
); );
}); });

View file

@ -7,8 +7,7 @@ import styled, { css } from "styled-components";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useMemo } from "preact/hooks"; import { useMemo } from "preact/hooks";
import Checkbox from "../../ui/Checkbox"; import { Checkbox, OverrideSwitch } from "@revoltchat/ui";
import { OverrideSwitch } from "@revoltchat/ui";
interface PermissionSelectProps { interface PermissionSelectProps {
id: keyof typeof Permission; id: keyof typeof Permission;
@ -136,7 +135,7 @@ export function PermissionSelect({
) : ( ) : (
<Checkbox <Checkbox
disabled={disabled} disabled={disabled}
checked={state === "Allow"} value={state === "Allow"}
onChange={() => onChange={() =>
onChange( onChange(
Long.fromNumber(value, false) Long.fromNumber(value, false)

View file

@ -1,123 +0,0 @@
import { Check } from "@styled-icons/boxicons-regular";
import styled, { css } from "styled-components/macro";
import { Children } from "../../types/Preact";
export const CheckboxBase = styled.label`
gap: 4px;
z-index: 1;
display: flex;
margin-top: 20px;
align-items: center;
border-radius: var(--border-radius);
cursor: pointer;
font-size: 18px;
user-select: none;
transition: 0.2s ease all;
input {
display: none;
}
&:hover {
.check {
background: var(--background);
}
}
&[disabled] {
opacity: 0.5;
cursor: not-allowed;
&:hover {
background: unset;
}
}
`;
const CheckboxContent = styled.span`
display: flex;
flex-grow: 1;
font-size: 14px;
gap: 2px;
font-weight: 600;
flex-direction: column;
`;
const CheckboxDescription = styled.span`
font-size: 0.75rem;
font-weight: 500;
color: var(--secondary-foreground);
`;
export const Checkmark = styled.div<{ checked: boolean; contrast?: boolean }>`
margin: 4px;
width: 24px;
height: 24px;
display: grid;
flex-shrink: 0;
place-items: center;
transition: 0.2s ease all;
border-radius: var(--border-radius);
background: var(--secondary-background);
svg {
color: var(--secondary-background);
}
${(props) =>
props.contrast &&
css`
background: var(--primary-background);
svg {
color: var(--primary-background);
}
`}
${(props) =>
props.checked &&
css`
background: var(--accent) !important;
`}
`;
export interface CheckboxProps {
checked: boolean;
disabled?: boolean;
contrast?: boolean;
className?: string;
children?: Children;
description?: Children;
onChange: (state: boolean) => void;
}
export default function Checkbox(props: CheckboxProps) {
return (
<CheckboxBase disabled={props.disabled} className={props.className}>
<CheckboxContent>
<span>{props.children}</span>
{props.description && (
<CheckboxDescription>
{props.description}
</CheckboxDescription>
)}
</CheckboxContent>
<input
type="checkbox"
checked={props.checked}
onChange={() =>
!props.disabled && props.onChange(!props.checked)
}
/>
<Checkmark
checked={props.checked}
contrast={props.contrast}
className="check">
<Check size={20} />
</Checkmark>
</CheckboxBase>
);
}

View file

@ -5,13 +5,12 @@ import styled from "styled-components/macro";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useEffect, useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import { Button } from "@revoltchat/ui"; import { Button, Checkbox } from "@revoltchat/ui";
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize"; import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
import { FileUploader } from "../../../context/revoltjs/FileUploads"; import { FileUploader } from "../../../context/revoltjs/FileUploads";
import Checkbox from "../../../components/ui/Checkbox";
import InputBox from "../../../components/ui/InputBox"; import InputBox from "../../../components/ui/InputBox";
interface Props { interface Props {
@ -120,14 +119,14 @@ export default observer(({ channel }: Props) => {
"" ""
) : ( ) : (
<Checkbox <Checkbox
checked={nsfw ?? false} value={nsfw ?? false}
onChange={(nsfwchange) => { onChange={(nsfwchange) => {
setNSFW(nsfwchange); setNSFW(nsfwchange);
if (!changed) setChanged(true); if (!changed) setChanged(true);
}} }}
description="Set this channel to NSFW."> title="NSFW"
NSFW description="Set this channel to NSFW."
</Checkbox> />
)} )}
<p> <p>
<Button onClick={save} palette="secondary" disabled={!changed}> <Button onClick={save} palette="secondary" disabled={!changed}>

View file

@ -3,14 +3,14 @@ import { observer } from "mobx-react-lite";
import styles from "./Panes.module.scss"; import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { Checkbox } from "@revoltchat/ui";
import { useApplicationState } from "../../../mobx/State"; import { useApplicationState } from "../../../mobx/State";
import { import {
AVAILABLE_EXPERIMENTS, AVAILABLE_EXPERIMENTS,
EXPERIMENTS, EXPERIMENTS,
} from "../../../mobx/stores/Experiments"; } from "../../../mobx/stores/Experiments";
import Checkbox from "../../../components/ui/Checkbox";
export const ExperimentsPage = observer(() => { export const ExperimentsPage = observer(() => {
const experiments = useApplicationState().experiments; const experiments = useApplicationState().experiments;
@ -22,11 +22,11 @@ export const ExperimentsPage = observer(() => {
{AVAILABLE_EXPERIMENTS.map((key) => ( {AVAILABLE_EXPERIMENTS.map((key) => (
<Checkbox <Checkbox
key={key} key={key}
checked={experiments.isEnabled(key)} value={experiments.isEnabled(key)}
onChange={(enabled) => experiments.setEnabled(key, enabled)} onChange={(enabled) => experiments.setEnabled(key, enabled)}
description={EXPERIMENTS[key].description}> description={EXPERIMENTS[key].description}
{EXPERIMENTS[key].title} title={EXPERIMENTS[key].title}
</Checkbox> />
))} ))}
{AVAILABLE_EXPERIMENTS.length === 0 && ( {AVAILABLE_EXPERIMENTS.length === 0 && (
<div className={styles.empty}> <div className={styles.empty}>

View file

@ -5,6 +5,8 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useMemo } from "preact/hooks"; import { useMemo } from "preact/hooks";
import { Checkbox } from "@revoltchat/ui";
import { useApplicationState } from "../../../mobx/State"; import { useApplicationState } from "../../../mobx/State";
import britannyFlagSVG from "../assets/flags/brittany.svg"; import britannyFlagSVG from "../assets/flags/brittany.svg";
@ -21,7 +23,6 @@ import {
Languages as Langs, Languages as Langs,
} from "../../../../external/lang/Languages"; } from "../../../../external/lang/Languages";
import Emoji from "../../../components/common/Emoji"; import Emoji from "../../../components/common/Emoji";
import Checkbox from "../../../components/ui/Checkbox";
import Tip from "../../../components/ui/Tip"; import Tip from "../../../components/ui/Tip";
type Key = [Language, LanguageEntry]; type Key = [Language, LanguageEntry];
@ -41,66 +42,82 @@ function Entry({ entry: [x, lang], selected, onSelect }: Props) {
<Checkbox <Checkbox
key={x} key={x}
className={styles.entry} className={styles.entry}
checked={selected} value={selected}
onChange={onSelect}> onChange={onSelect}
<div className={styles.flag}> title={
{lang.i18n === "vec" ? ( <>
<img <div className={styles.flag}>
src={venetoFlagSVG} {lang.i18n === "vec" ? (
width={42} <img
loading="lazy" src={venetoFlagSVG}
style={{ objectFit: "cover", borderRadius: "6px" }} width={42}
/> loading="lazy"
) : lang.i18n === "br" ? ( style={{
<img objectFit: "cover",
src={britannyFlagSVG} borderRadius: "6px",
width={42} }}
loading="lazy" />
style={{ objectFit: "cover", borderRadius: "6px" }} ) : lang.i18n === "br" ? (
/> <img
) : lang.i18n === "ckb" ? ( src={britannyFlagSVG}
<img width={42}
src={kurdistanFlagSVG} loading="lazy"
width={42} style={{
loading="lazy" objectFit: "cover",
style={{ objectFit: "cover", borderRadius: "6px" }} borderRadius: "6px",
/> }}
) : lang.i18n === "eo" ? ( />
<img ) : lang.i18n === "ckb" ? (
src={esperantoFlagSVG} <img
width={42} src={kurdistanFlagSVG}
loading="lazy" width={42}
style={{ objectFit: "cover", borderRadius: "6px" }} loading="lazy"
/> style={{
) : lang.i18n === "ta" ? ( objectFit: "cover",
<img borderRadius: "6px",
src={tamilFlagPNG} }}
width={42} />
loading="lazy" ) : lang.i18n === "eo" ? (
style={{ objectFit: "cover" }} <img
/> src={esperantoFlagSVG}
) : lang.emoji === "🙂" ? ( width={42}
<img loading="lazy"
src={tokiponaSVG} style={{
width={42} objectFit: "cover",
loading="lazy" borderRadius: "6px",
style={{ borderRadius: "6px" }} }}
/> />
) : lang.emoji === "🪄" ? ( ) : lang.i18n === "ta" ? (
<img <img
src={enchantingTableWEBP} src={tamilFlagPNG}
width={42} width={42}
loading="lazy" loading="lazy"
style={{ objectFit: "contain" }} style={{ objectFit: "cover" }}
/> />
) : ( ) : lang.emoji === "🙂" ? (
<Emoji size={42} emoji={lang.emoji} /> <img
)} src={tokiponaSVG}
</div> width={42}
<span className={styles.description}> loading="lazy"
{lang.display} {lang.verified && <Check size={16} />} style={{ borderRadius: "6px" }}
</span> />
</Checkbox> ) : lang.emoji === "🪄" ? (
<img
src={enchantingTableWEBP}
width={42}
loading="lazy"
style={{ objectFit: "contain" }}
/>
) : (
<Emoji size={42} emoji={lang.emoji} />
)}
</div>
<span className={styles.description}>
{lang.display} {lang.verified && <Check size={16} />}
</span>
</>
}
/>
); );
} }

View file

@ -11,7 +11,7 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useCallback, useEffect, useState } from "preact/hooks"; import { useCallback, useEffect, useState } from "preact/hooks";
import { Button } from "@revoltchat/ui"; import { Button, Checkbox } from "@revoltchat/ui";
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize"; import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
import { internalEmit } from "../../../lib/eventEmitter"; import { internalEmit } from "../../../lib/eventEmitter";
@ -28,7 +28,6 @@ import AutoComplete, {
import CollapsibleSection from "../../../components/common/CollapsibleSection"; import CollapsibleSection from "../../../components/common/CollapsibleSection";
import Tooltip from "../../../components/common/Tooltip"; import Tooltip from "../../../components/common/Tooltip";
import UserIcon from "../../../components/common/user/UserIcon"; import UserIcon from "../../../components/common/user/UserIcon";
import Checkbox from "../../../components/ui/Checkbox";
import InputBox from "../../../components/ui/InputBox"; import InputBox from "../../../components/ui/InputBox";
import Tip from "../../../components/ui/Tip"; import Tip from "../../../components/ui/Tip";
import CategoryButton from "../../../components/ui/fluent/CategoryButton"; import CategoryButton from "../../../components/ui/fluent/CategoryButton";
@ -436,15 +435,14 @@ function BotCard({ bot, onDelete, onUpdate }: Props) {
/> />
</CollapsibleSection> </CollapsibleSection>
<Checkbox <Checkbox
checked={data.public} value={data.public}
disabled={saving} disabled={saving}
contrast title={<Text id="app.settings.pages.bots.public_bot" />}
description={ description={
<Text id="app.settings.pages.bots.public_bot_desc" /> <Text id="app.settings.pages.bots.public_bot_desc" />
} }
onChange={(v) => setData({ ...data, public: v })}> onChange={(v) => setData({ ...data, public: v })}
<Text id="app.settings.pages.bots.public_bot" /> />
</Checkbox>
<h3> <h3>
<Text id="app.settings.pages.bots.interactions_url" /> <Text id="app.settings.pages.bots.interactions_url" />
</h3> </h3>

View file

@ -2,12 +2,12 @@ import { Refresh } from "@styled-icons/boxicons-regular";
import { useEffect, useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import { Button } from "@revoltchat/ui"; import { Button, Checkbox } from "@revoltchat/ui";
import RLogo from "../assets/revolt_r.svg";
import Checkbox from "../../../components/ui/Checkbox";
import Tip from "../../../components/ui/Tip"; import Tip from "../../../components/ui/Tip";
import CategoryButton from "../../../components/ui/fluent/CategoryButton"; import CategoryButton from "../../../components/ui/fluent/CategoryButton";
import RLogo from "../assets/revolt_r.svg";
export function Native() { export function Native() {
if (typeof window.native === "undefined") return null; if (typeof window.native === "undefined") return null;
@ -30,7 +30,7 @@ export function Native() {
<Tip hideSeparator>Some options might require a restart.</Tip> <Tip hideSeparator>Some options might require a restart.</Tip>
<h3>App Behavior</h3> <h3>App Behavior</h3>
<Checkbox <Checkbox
checked={autoStart ?? false} value={autoStart ?? false}
disabled={typeof autoStart === "undefined"} disabled={typeof autoStart === "undefined"}
onChange={async (v) => { onChange={async (v) => {
if (v) { if (v) {
@ -41,12 +41,12 @@ export function Native() {
setAutoStart(v); setAutoStart(v);
}} }}
description="Launch Revolt when you log into your computer."> title="Start with computer"
Start with computer description="Launch Revolt when you log into your computer."
</Checkbox> />
<Checkbox <Checkbox
checked={config.minimiseToTray} value={config.minimiseToTray}
onChange={(minimiseToTray) => { onChange={(minimiseToTray) => {
window.native.set("minimiseToTray", minimiseToTray); window.native.set("minimiseToTray", minimiseToTray);
setConfig({ setConfig({
@ -54,11 +54,11 @@ export function Native() {
minimiseToTray, minimiseToTray,
}); });
}} }}
description="Instead of closing, Revolt will hide in your tray."> title="Minimise to Tray"
Minimise to Tray description="Instead of closing, Revolt will hide in your tray."
</Checkbox> />
<Checkbox <Checkbox
checked={config.discordRPC} value={config.discordRPC}
onChange={(discordRPC) => { onChange={(discordRPC) => {
window.native.set("discordRPC", discordRPC); window.native.set("discordRPC", discordRPC);
setConfig({ setConfig({
@ -66,11 +66,11 @@ export function Native() {
discordRPC, discordRPC,
}); });
}} }}
description="Rep Revolt on your Discord status."> title="Enable Discord status"
Enable Discord status description="Rep Revolt on your Discord status."
</Checkbox> />
<Checkbox <Checkbox
checked={config.build === "nightly"} value={config.build === "nightly"}
onChange={(nightly) => { onChange={(nightly) => {
const build = nightly ? "nightly" : "stable"; const build = nightly ? "nightly" : "stable";
window.native.set("build", build); window.native.set("build", build);
@ -80,12 +80,13 @@ export function Native() {
build, build,
}); });
}} }}
description="Use the beta branch of Revolt."> title="Revolt Nightly"
Revolt Nightly description="Use the beta branch of Revolt."
</Checkbox> />
<h3>Titlebar</h3> <h3>Titlebar</h3>
<Checkbox <Checkbox
checked={!config.frame} value={!config.frame}
onChange={(frame) => { onChange={(frame) => {
window.native.set("frame", !frame); window.native.set("frame", !frame);
setHintRelaunch(true); setHintRelaunch(true);
@ -94,12 +95,12 @@ export function Native() {
frame: !frame, frame: !frame,
}); });
}} }}
description={<>Let Revolt use its own window frame.</>}> title="Custom window frame"
Custom window frame description="Let Revolt use its own window frame."
</Checkbox> />
<Checkbox //FIXME: In Titlebar.tsx, enable .quick css <Checkbox //FIXME: In Titlebar.tsx, enable .quick css
disabled={true} disabled={true}
checked={!config.frame} value={!config.frame}
onChange={(frame) => { onChange={(frame) => {
window.native.set("frame", !frame); window.native.set("frame", !frame);
setHintRelaunch(true); setHintRelaunch(true);
@ -108,12 +109,12 @@ export function Native() {
frame: !frame, frame: !frame,
}); });
}} }}
description="Show mute/deafen buttons on the titlebar."> title="Enable quick action buttons"
Enable quick action buttons description="Show mute/deafen buttons on the titlebar."
</Checkbox> />
<h3>Advanced</h3> <h3>Advanced</h3>
<Checkbox <Checkbox
checked={config.hardwareAcceleration} value={config.hardwareAcceleration}
onChange={async (hardwareAcceleration) => { onChange={async (hardwareAcceleration) => {
window.native.set( window.native.set(
"hardwareAcceleration", "hardwareAcceleration",
@ -125,9 +126,10 @@ export function Native() {
hardwareAcceleration, hardwareAcceleration,
}); });
}} }}
description="Uses your GPU to render the app, disable if you run into visual issues."> title="Hardware Acceleration"
Hardware Acceleration description="Uses your GPU to render the app, disable if you run into visual issues."
</Checkbox> />
<p style={{ display: "flex", gap: "8px" }}> <p style={{ display: "flex", gap: "8px" }}>
<Button <Button
palette="secondary" palette="secondary"
@ -161,8 +163,9 @@ export function Native() {
) : ( ) : (
<> <>
<Checkbox <Checkbox
checked={confirmDev} value={confirmDev}
onChange={setConfirmDev} onChange={setConfirmDev}
title="I understand there's no going back."
description={ description={
<> <>
This will change the app to the 'dev' branch, This will change the app to the 'dev' branch,
@ -178,9 +181,8 @@ export function Native() {
<br /> <br />
<code>yarn dev --port 3001</code> <code>yarn dev --port 3001</code>
</> </>
}> }
I understand there's no going back. />
</Checkbox>
<p> <p>
<Button <Button
palette="error" palette="error"

View file

@ -4,6 +4,8 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useContext, useEffect, useState } from "preact/hooks"; import { useContext, useEffect, useState } from "preact/hooks";
import { Checkbox } from "@revoltchat/ui";
import { urlBase64ToUint8Array } from "../../../lib/conversion"; import { urlBase64ToUint8Array } from "../../../lib/conversion";
import { useApplicationState } from "../../../mobx/State"; import { useApplicationState } from "../../../mobx/State";
@ -11,8 +13,6 @@ import { useApplicationState } from "../../../mobx/State";
import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { AppContext } from "../../../context/revoltjs/RevoltClient";
import Checkbox from "../../../components/ui/Checkbox";
export const Notifications = observer(() => { export const Notifications = observer(() => {
const client = useContext(AppContext); const client = useContext(AppContext);
const { openScreen } = useIntermediate(); const { openScreen } = useIntermediate();
@ -38,7 +38,10 @@ export const Notifications = observer(() => {
</h3> </h3>
<Checkbox <Checkbox
disabled={!("Notification" in window)} disabled={!("Notification" in window)}
checked={settings.get("notifications:desktop", false)!} value={settings.get("notifications:desktop", false)!}
title={
<Text id="app.settings.pages.notifications.enable_desktop" />
}
description={ description={
<Text id="app.settings.pages.notifications.descriptions.enable_desktop" /> <Text id="app.settings.pages.notifications.descriptions.enable_desktop" />
} }
@ -56,12 +59,14 @@ export const Notifications = observer(() => {
} }
settings.set("notifications:desktop", desktopEnabled); settings.set("notifications:desktop", desktopEnabled);
}}> }}
<Text id="app.settings.pages.notifications.enable_desktop" /> />
</Checkbox>
<Checkbox <Checkbox
disabled={typeof pushEnabled === "undefined"} disabled={typeof pushEnabled === "undefined"}
checked={pushEnabled ?? false} value={pushEnabled ?? false}
title={
<Text id="app.settings.pages.notifications.enable_push" />
}
description={ description={
<Text id="app.settings.pages.notifications.descriptions.enable_push" /> <Text id="app.settings.pages.notifications.descriptions.enable_push" />
} }
@ -102,21 +107,24 @@ export const Notifications = observer(() => {
} catch (err) { } catch (err) {
console.error("Failed to enable push!", err); console.error("Failed to enable push!", err);
} }
}}> }}
<Text id="app.settings.pages.notifications.enable_push" /> />
</Checkbox>
<h3> <h3>
<Text id="app.settings.pages.notifications.sounds" /> <Text id="app.settings.pages.notifications.sounds" />
</h3> </h3>
{settings.sounds.getState().map(({ id, enabled }) => ( {settings.sounds.getState().map(({ id, enabled }) => (
<Checkbox <Checkbox
key={id} key={id}
checked={enabled} value={enabled}
title={
<Text
id={`app.settings.pages.notifications.sound.${id}`}
/>
}
onChange={(enabled) => onChange={(enabled) =>
settings.sounds.setEnabled(id, enabled) settings.sounds.setEnabled(id, enabled)
}> }
<Text id={`app.settings.pages.notifications.sound.${id}`} /> />
</Checkbox>
))} ))}
</div> </div>
); );

View file

@ -485,7 +485,7 @@
} }
} }
.entry > span > span { .entry > div div {
gap: 8px; gap: 8px;
display: flex; display: flex;
align-items: center; align-items: center;

View file

@ -1,15 +1,12 @@
import { Check } from "@styled-icons/boxicons-regular";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import styled from "styled-components";
import styles from "./Panes.module.scss"; import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { Button } from "@revoltchat/ui"; import { Button, Checkbox } from "@revoltchat/ui";
import { useApplicationState } from "../../../mobx/State"; import { useApplicationState } from "../../../mobx/State";
import { CheckboxBase, Checkmark } from "../../../components/ui/Checkbox";
import Tip from "../../../components/ui/Tip"; import Tip from "../../../components/ui/Tip";
// Just keeping this here for general purpose. Should probably be exported // Just keeping this here for general purpose. Should probably be exported
@ -21,45 +18,10 @@ interface Plugin {
enabled: boolean | undefined; enabled: boolean | undefined;
} }
const CustomCheckboxBase = styled(CheckboxBase)`
margin-top: 0 !important;
`;
export interface CheckboxProps {
checked: boolean;
disabled?: boolean;
onChange: (state: boolean) => void;
}
function PluginCheckbox(props: CheckboxProps) {
// HACK HACK HACK(lexisother): THIS ENTIRE THING IS A HACK!!!!
/*
Until some reviewer points me in the right direction, I've resorted to
fabricating my own checkbox component.
"WHY?!", you might ask. Well, the normal `Checkbox` component can take
textual contents, and *also* adds a `margin-top` of 20 pixels.
We... don't need that. At all. *Especially* the margin. It makes our card
look disproportionate.
Apologies, @insert!
*/
return (
<CustomCheckboxBase disabled={props.disabled}>
<input
type="checkbox"
checked={props.checked}
onChange={() =>
!props.disabled && props.onChange(!props.checked)
}
/>
<Checkmark checked={props.checked} className="check">
<Check size={20} />
</Checkmark>
</CustomCheckboxBase>
);
}
interface CardProps { interface CardProps {
plugin: Plugin; plugin: Plugin;
} }
function PluginCard({ plugin }: CardProps) { function PluginCard({ plugin }: CardProps) {
const plugins = useApplicationState().plugins; const plugins = useApplicationState().plugins;
@ -70,12 +32,14 @@ function PluginCard({ plugin }: CardProps) {
<div key={plugin.id} className={styles.botCard}> <div key={plugin.id} className={styles.botCard}>
<div className={styles.infocontainer}> <div className={styles.infocontainer}>
<div className={styles.infoheader}> <div className={styles.infoheader}>
<div className={styles.container}> <Checkbox
{plugin.namespace} / {plugin.id}
</div>
<PluginCheckbox
key={plugin.id} key={plugin.id}
checked={plugin.enabled!} value={plugin.enabled!}
title={
<>
{plugin.namespace} / {plugin.id}
</>
}
onChange={() => { onChange={() => {
!plugin.enabled !plugin.enabled
? plugins.load(plugin.namespace, plugin.id) ? plugins.load(plugin.namespace, plugin.id)

View file

@ -3,11 +3,11 @@ import { observer } from "mobx-react-lite";
import styles from "./Panes.module.scss"; import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { Checkbox } from "@revoltchat/ui";
import { useApplicationState } from "../../../mobx/State"; import { useApplicationState } from "../../../mobx/State";
import { SyncKeys } from "../../../mobx/stores/Sync"; import { SyncKeys } from "../../../mobx/stores/Sync";
import Checkbox from "../../../components/ui/Checkbox";
export const Sync = observer(() => { export const Sync = observer(() => {
const sync = useApplicationState().sync; const sync = useApplicationState().sync;
@ -30,15 +30,15 @@ export const Sync = observer(() => {
).map(([key, title]) => ( ).map(([key, title]) => (
<Checkbox <Checkbox
key={key} key={key}
checked={sync.isEnabled(key)} value={sync.isEnabled(key)}
title={<Text id={`app.settings.pages.${title}`} />}
description={ description={
<Text <Text
id={`app.settings.pages.sync.descriptions.${key}`} id={`app.settings.pages.sync.descriptions.${key}`}
/> />
} }
onChange={() => sync.toggle(key)}> onChange={() => sync.toggle(key)}
<Text id={`app.settings.pages.${title}`} /> />
</Checkbox>
))} ))}
{/*<h5 style={{ marginTop: "20px", color: "grey" }}> {/*<h5 style={{ marginTop: "20px", color: "grey" }}>
Last sync at 12:00 Last sync at 12:00

View file

@ -9,11 +9,10 @@ import styles from "./Panes.module.scss";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useEffect, useMemo, useState } from "preact/hooks"; import { useEffect, useMemo, useState } from "preact/hooks";
import { Button, Preloader } from "@revoltchat/ui"; import { Button, Checkbox, Preloader } from "@revoltchat/ui";
import UserIcon from "../../../components/common/user/UserIcon"; import UserIcon from "../../../components/common/user/UserIcon";
import { Username } from "../../../components/common/user/UserShort"; import { Username } from "../../../components/common/user/UserShort";
import Checkbox from "../../../components/ui/Checkbox";
import IconButton from "../../../components/ui/IconButton"; import IconButton from "../../../components/ui/IconButton";
import InputBox from "../../../components/ui/InputBox"; import InputBox from "../../../components/ui/InputBox";
import Overline from "../../../components/ui/Overline"; import Overline from "../../../components/ui/Overline";
@ -54,7 +53,15 @@ const Inner = observer(({ member }: InnerProps) => {
return ( return (
<Checkbox <Checkbox
key={key} key={key}
checked={roles.includes(key) ?? false} value={roles.includes(key) ?? false}
title={
<span
style={{
color: role.colour,
}}>
{role.name}
</span>
}
onChange={(v) => { onChange={(v) => {
if (v) { if (v) {
setRoles([...roles, key]); setRoles([...roles, key]);
@ -63,14 +70,8 @@ const Inner = observer(({ member }: InnerProps) => {
roles.filter((x) => x !== key), roles.filter((x) => x !== key),
); );
} }
}}> }}
<span />
style={{
color: role.colour,
}}>
{role.name}
</span>
</Checkbox>
); );
})} })}
<Button <Button

View file

@ -5,16 +5,21 @@ import { Server } from "revolt.js";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useMemo, useState } from "preact/hooks"; import { useMemo, useState } from "preact/hooks";
import { useIntermediate } from "../../../context/intermediate/Intermediate"; import {
Button,
PermissionsLayout,
SpaceBetween,
H1,
Checkbox,
} from "@revoltchat/ui";
import Checkbox from "../../../components/ui/Checkbox"; import { useIntermediate } from "../../../context/intermediate/Intermediate";
import ColourSwatches from "../../../components/ui/ColourSwatches";
import InputBox from "../../../components/ui/InputBox";
import Overline from "../../../components/ui/Overline";
import { Button, PermissionsLayout, SpaceBetween, H1 } from "@revoltchat/ui";
import { PermissionList } from "../../../components/settings/roles/PermissionList"; import { PermissionList } from "../../../components/settings/roles/PermissionList";
import { RoleOrDefault } from "../../../components/settings/roles/RoleSelection"; import { RoleOrDefault } from "../../../components/settings/roles/RoleSelection";
import ColourSwatches from "../../../components/ui/ColourSwatches";
import InputBox from "../../../components/ui/InputBox";
import Overline from "../../../components/ui/Overline";
interface Props { interface Props {
server: Server; server: Server;
@ -169,17 +174,19 @@ export const Roles = observer(({ server }: Props) => {
</Overline> </Overline>
<p> <p>
<Checkbox <Checkbox
checked={ value={
currentRoleValue.hoist ?? false currentRoleValue.hoist ?? false
} }
onChange={(hoist) => onChange={(hoist) =>
setValue({ ...value, hoist }) setValue({ ...value, hoist })
} }
title={
<Text id="app.settings.permissions.hoist_role" />
}
description={ description={
<Text id="app.settings.permissions.hoist_desc" /> <Text id="app.settings.permissions.hoist_desc" />
}> }
<Text id="app.settings.permissions.hoist_role" /> />
</Checkbox>
</p> </p>
</section> </section>
<section> <section>

View file

@ -2220,9 +2220,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@revoltchat/ui@npm:1.0.34": "@revoltchat/ui@portal:../components::locator=client%40workspace%3A.":
version: 1.0.34 version: 0.0.0-use.local
resolution: "@revoltchat/ui@npm:1.0.34" resolution: "@revoltchat/ui@portal:../components::locator=client%40workspace%3A."
dependencies: dependencies:
"@styled-icons/boxicons-logos": ^10.38.0 "@styled-icons/boxicons-logos": ^10.38.0
"@styled-icons/boxicons-regular": ^10.38.0 "@styled-icons/boxicons-regular": ^10.38.0
@ -2235,9 +2235,8 @@ __metadata:
react-device-detect: "*" react-device-detect: "*"
react-virtuoso: "*" react-virtuoso: "*"
revolt.js: "*" revolt.js: "*"
checksum: 576a147c945cc3c9c8fb0555007b1048017551139d6b6dd7f0e9af66a1f5e595a46e73b853258a5048563af80c470230048ab214784cf14f347cf61b56dbbc07
languageName: node languageName: node
linkType: hard linkType: soft
"@rollup/plugin-babel@npm:^5.2.0": "@rollup/plugin-babel@npm:^5.2.0":
version: 5.3.0 version: 5.3.0