Give setting components a facelift

This commit is contained in:
Zerebos 2024-12-08 20:40:57 -05:00
parent 25d3dcfac6
commit db908b71e4
No known key found for this signature in database
11 changed files with 102 additions and 67 deletions

View File

@ -155,10 +155,10 @@ const UI = {
* @param {ReactElement} [setting.children] Only used for "custom" type * @param {ReactElement} [setting.children] Only used for "custom" type
* @param {CallableFunction} [setting.onChange] Callback when the value changes (only argument is new value) * @param {CallableFunction} [setting.onChange] Callback when the value changes (only argument is new value)
* @param {boolean} [setting.disabled=false] Whether this setting is disabled * @param {boolean} [setting.disabled=false] Whether this setting is disabled
* @param {boolean} [setting.inline=true] Whether the input should render inline with the name (this is false by default for slider, color, and radio types) * @param {boolean} [setting.inline=true] Whether the input should render inline with the name (this is false by default for radio type)
* @returns A SettingItem with a an input as the child * @returns A SettingItem with a an input as the child
*/ */
buildSetting(setting) { buildSettingItem(setting) {
return buildSetting(setting); return buildSetting(setting);
}, },

View File

@ -119,8 +119,8 @@ export class Filters {
* @returns {module:WebpackModules.Filters~filter} - Combinatory filter of all arguments * @returns {module:WebpackModules.Filters~filter} - Combinatory filter of all arguments
*/ */
static combine(...filters) { static combine(...filters) {
return module => { return (exports, module, id) => {
return filters.every(filter => filter(module)); return filters.every(filter => filter(exports, module, id));
}; };
} }
} }
@ -515,7 +515,7 @@ export default class WebpackModules {
const listeners = [...this.listeners]; const listeners = [...this.listeners];
for (let i = 0; i < listeners.length; i++) { for (let i = 0; i < listeners.length; i++) {
try {listeners[i](exports);} try {listeners[i](exports, module, module.id);}
catch (error) { catch (error) {
Logger.stacktrace("WebpackModules", "Could not fire callback listener:", error); Logger.stacktrace("WebpackModules", "Could not fire callback listener:", error);
} }

View File

@ -1,5 +1,6 @@
.bd-color-picker-container { .bd-color-picker-container {
display: flex; display: flex;
justify-content: center;
} }
.bd-color-picker-container.bd-color-picker-disabled { .bd-color-picker-container.bd-color-picker-disabled {
@ -20,8 +21,8 @@
.bd-color-picker-default { .bd-color-picker-default {
cursor: pointer; cursor: pointer;
width: 72px; width: 75px;
height: 54px; height: 60px;
border-radius: 4px; border-radius: 4px;
margin-right: 9px; margin-right: 9px;
display: flex; display: flex;
@ -39,13 +40,14 @@
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 5px; right: 5px;
pointer-events: none;
} }
.bd-color-picker { .bd-color-picker {
outline: none; outline: none;
width: 70px; width: 75px;
border: none; border: none;
height: 54px; height: 60px;
margin-top: 1px; margin-top: 1px;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
@ -60,16 +62,35 @@
flex-wrap: wrap; flex-wrap: wrap;
align-content: flex-start; align-content: flex-start;
margin-left: 5px !important; margin-left: 5px !important;
max-width: 340px; max-width: 330px;
} }
.bd-color-picker-swatch-item { .bd-color-picker-swatch-item {
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
width: 23px; width: 15px;
height: 23px; height: 15px;
margin: 4px; margin: 4px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.bd-setting-item.inline .bd-color-picker-swatch {
max-width: 220px;
margin-top: 1px;
}
.bd-setting-item.inline .bd-color-picker-default,
.bd-setting-item.inline .bd-color-picker {
width: 50px;
height: 40px
}
.bd-setting-item.inline .bd-color-picker-swatch-item {
height: 18px;
width: 18px;
margin: 2px 2px;
}

View File

@ -1,48 +1,54 @@
.bd-setting-item.inline .bd-file-input-wrap {
max-width: 300px;
}
.bd-file-input-wrap { .bd-file-input-wrap {
display: flex;
align-items: center;
gap: 5px;
position: relative; position: relative;
min-width: 250px;
box-sizing: border-box;
border-radius: 3px;
background-color: hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .1);
border: 1px solid hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .3);
padding: 0 4px;
height: 40px;
} }
.bd-file-input { .bd-file-input {
flex: 1;
outline: none;
color: var(--text-normal); color: var(--text-normal);
background-color: var(--input-background);
min-width: 250px;
width: 100%;
font-size: 16px; font-size: 16px;
border-radius: 3px; font-weight: 600;
padding: 10px; width: 100%;
height: 40px; cursor: pointer;
box-sizing: border-box;
overflow: hidden;
border: none;
} }
.bd-file-input::-webkit-file-upload-button { .bd-file-input::-webkit-file-upload-button {
color: white; height: 0;
background: #3E82E5; width: 0;
outline: 0; padding: 0 !important;
border: 0; margin: 0;
padding: 12px 16px!important; visibility: hidden;
margin-top: -10px;
margin-left: -10px;
margin-right: 10px;
bottom: 0;
border-radius: 3px 0 0 3px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
user-select: none; user-select: none;
pointer-events: none;
}
.bd-file-input-wrap .bd-file-input-browse {
padding: 7px 16px;
} }
.bd-file-input-wrap .bd-file-input-clear { .bd-file-input-wrap .bd-file-input-clear {
position: absolute; margin-left: 5px;
top: 50%; /* background: none!important; */
right: 5px;
transform: translateY(-50%);
opacity: 0.5; opacity: 0.5;
padding-right: 4px!important;
} }
.bd-file-input-wrap .bd-file-input-clear:hover { .bd-file-input-wrap .bd-file-input-clear:hover {
background: none; /* background: none; */
opacity: 1; opacity: 1;
} }
@ -56,6 +62,7 @@
opacity: 0.5; opacity: 0.5;
} }
.bd-file-input-wrap.bd-file-input-disabled .bd-file-input-browse,
.bd-file-input-wrap.bd-file-input-disabled .bd-file-input, .bd-file-input-wrap.bd-file-input-disabled .bd-file-input,
.bd-file-input-wrap.bd-file-input-disabled .bd-file-input-clear { .bd-file-input-wrap.bd-file-input-disabled .bd-file-input-clear {
pointer-events: none; pointer-events: none;

View File

@ -1,11 +1,14 @@
.bd-keybind-wrap { .bd-keybind-wrap {
display: flex;
align-items: center;
gap: 5px;
position: relative; position: relative;
min-width: 250px; min-width: 250px;
box-sizing: border-box; box-sizing: border-box;
border-radius: 3px; border-radius: 3px;
background-color: hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .1); background-color: hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .1);
border: 1px solid hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .3); border: 1px solid hsla(0, calc(var(--saturation-factor, 1)*0%), 0%, .3);
padding: 10px; padding: 0 4px;
height: 40px; height: 40px;
cursor: pointer; cursor: pointer;
} }
@ -20,6 +23,7 @@
} }
.bd-keybind-wrap input { .bd-keybind-wrap input {
flex: 1;
outline: none; outline: none;
border: none; border: none;
pointer-events: none; pointer-events: none;
@ -27,7 +31,11 @@
background: none; background: none;
font-size: 16px; font-size: 16px;
text-transform: uppercase; text-transform: uppercase;
font-weight: 700; font-weight: 600;
}
.bd-keybind-wrap input::placeholder {
text-transform: capitalize;
} }
.bd-keybind-wrap.recording { .bd-keybind-wrap.recording {
@ -38,28 +46,23 @@
box-shadow: 0 0 6px hsla(359, calc(var(--saturation-factor, 1)*82.6%), 59.4%, .3); box-shadow: 0 0 6px hsla(359, calc(var(--saturation-factor, 1)*82.6%), 59.4%, .3);
} }
.bd-keybind-controls { .bd-keybind-wrap.recording input {
position: absolute; color: hsl(359, calc(var(--saturation-factor, 1)*82.6%), 59.4%)
right: 5px;
top: 3px;
display: flex;
align-items: center;
gap: 5px;
} }
.bd-keybind-controls .bd-keybind-record { .bd-keybind-wrap .bd-keybind-record {
padding: 4px 8px; padding: 3px 8px;
} }
.bd-keybind-clear { .bd-keybind-clear {
margin-left: 5px; margin-left: 5px;
background: none!important; /* background: none!important; */
opacity: 0.5; opacity: 0.5;
padding-right: 4px!important; padding-right: 4px!important;
} }
.bd-keybind-clear:hover { .bd-keybind-clear:hover {
background: none; /* background: none; */
opacity: 1; opacity: 1;
} }

View File

@ -5,7 +5,8 @@
.bd-radio-option { .bd-radio-option {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 10px; border-left: 3px solid transparent;
padding: 10px 10px 10px 7px;
margin-bottom: 8px; margin-bottom: 8px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;

View File

@ -68,7 +68,7 @@ export default function Color({value: initialValue, onChange, colors = defaultCo
const intValue = resolveColor(value, false); const intValue = resolveColor(value, false);
return <div className={`bd-color-picker-container ${disabled ? "bd-color-picker-disabled" : ""}`}> return <div className={`bd-color-picker-container ${disabled ? "bd-color-picker-disabled" : ""}`}>
<div className="bd-color-picker-controls"> <div className="bd-color-picker-controls">
<DiscordModules.Tooltip text="Default" position="bottom"> {defaultValue && <DiscordModules.Tooltip text="Default" position="bottom">
{props => ( {props => (
<div {...props} className="bd-color-picker-default" style={{backgroundColor: resolveColor(defaultValue)}} onClick={() => change({target: {value: defaultValue}})}> <div {...props} className="bd-color-picker-default" style={{backgroundColor: resolveColor(defaultValue)}} onClick={() => change({target: {value: defaultValue}})}>
{intValue === resolveColor(defaultValue, false) {intValue === resolveColor(defaultValue, false)
@ -77,7 +77,7 @@ export default function Color({value: initialValue, onChange, colors = defaultCo
} }
</div> </div>
)} )}
</DiscordModules.Tooltip> </DiscordModules.Tooltip>}
<DiscordModules.Tooltip text={Strings.Settings.customColor} position="bottom"> <DiscordModules.Tooltip text={Strings.Settings.customColor} position="bottom">
{props => ( {props => (
<div className="bd-color-picker-custom"> <div className="bd-color-picker-custom">
@ -87,7 +87,7 @@ export default function Color({value: initialValue, onChange, colors = defaultCo
)} )}
</DiscordModules.Tooltip> </DiscordModules.Tooltip>
</div> </div>
<div className="bd-color-picker-swatch"> {colors?.length > 0 && <div className="bd-color-picker-swatch">
{ {
colors.map((int, index) => ( colors.map((int, index) => (
<div key={index} className="bd-color-picker-swatch-item" style={{backgroundColor: resolveColor(int)}} onClick={() => change({target: {value: int}})}> <div key={index} className="bd-color-picker-swatch-item" style={{backgroundColor: resolveColor(int)}} onClick={() => change({target: {value: int}})}>
@ -98,6 +98,6 @@ export default function Color({value: initialValue, onChange, colors = defaultCo
</div> </div>
)) ))
} }
</div> </div>}
</div>; </div>;
} }

View File

@ -28,7 +28,12 @@ export default function Filepicker({multiple, accept, clearable, onChange, disab
actions.clear = clear; actions.clear = clear;
}, [clear, actions]); }, [clear, actions]);
const onClick = useCallback(() => {
inputRef.current?.click();
}, []);
return <div className={`bd-file-input-wrap ${disabled ? "bd-file-input-disabled" : ""}`}> return <div className={`bd-file-input-wrap ${disabled ? "bd-file-input-disabled" : ""}`}>
<Button size={Button.Sizes.ICON} look={Button.Looks.FILLED} color={Button.Colors.PRIMARY} className="bd-file-input-browse" onClick={onClick}>Browse</Button>
<input onChange={change} type="file" className="bd-file-input" multiple={multiple} accept={accept} disabled={disabled} ref={inputRef} /> <input onChange={change} type="file" className="bd-file-input" multiple={multiple} accept={accept} disabled={disabled} ref={inputRef} />
{clearable && <Button size={Button.Sizes.ICON} look={Button.Looks.BLANK} onClick={clear} className="bd-file-input-clear"><Close size="24px" /></Button>} {clearable && <Button size={Button.Sizes.ICON} look={Button.Looks.BLANK} onClick={clear} className="bd-file-input-clear"><Close size="24px" /></Button>}
</div>; </div>;

View File

@ -7,7 +7,7 @@ import Close from "@ui/icons/close";
const {useState, useCallback, useEffect} = React; const {useState, useCallback, useEffect} = React;
export default function Keybind({value: initialValue, onChange, max = 4, clearable = true, disabled}) { export default function Keybind({value: initialValue, onChange, max = 4, clearable = false, disabled}) {
const [state, setState] = useState({value: initialValue, isRecording: false, accum: []}); const [state, setState] = useState({value: initialValue, isRecording: false, accum: []});
useEffect(() => { useEffect(() => {
@ -60,12 +60,10 @@ export default function Keybind({value: initialValue, onChange, max = 4, clearab
}, [state, clearKeybind, disabled]); }, [state, clearKeybind, disabled]);
const displayValue = state.isRecording ? "Recording..." : !state.value.length ? "N/A" : state.value.join(" + "); const displayValue = !state.value.length ? "" : state.value.map(k => k === "Control" ? "Ctrl" : k).join(" + ");
return <div className={"bd-keybind-wrap" + (state.isRecording ? " recording" : "") + (disabled ? " bd-keybind-disabled" : "")} onClick={onClick}> return <div className={"bd-keybind-wrap" + (state.isRecording ? " recording" : "") + (disabled ? " bd-keybind-disabled" : "")} onClick={onClick}>
<input readOnly={true} type="text" className="bd-keybind-input" value={displayValue} disabled={disabled} /> <Button size={Button.Sizes.ICON} look={Button.Looks.FILLED} color={state.isRecording ? Button.Colors.RED : Button.Colors.PRIMARY} className="bd-keybind-record" onClick={onClick}><Keyboard size="24px" /></Button>
<div className="bd-keybind-controls"> <input readOnly={true} type="text" className="bd-keybind-input" value={displayValue} placeholder="No keybind set" disabled={disabled} />
<Button size={Button.Sizes.ICON} look={Button.Looks.FILLED} color={state.isRecording ? Button.Colors.RED : Button.Colors.BRAND} className="bd-keybind-record" onClick={onClick}><Keyboard size="24px" /></Button>
{clearable && <Button size={Button.Sizes.ICON} look={Button.Looks.BLANK} onClick={clearKeybind} className="bd-keybind-clear"><Close size="24px" /></Button>} {clearable && <Button size={Button.Sizes.ICON} look={Button.Looks.BLANK} onClick={clearKeybind} className="bd-keybind-clear"><Close size="24px" /></Button>}
</div>
</div>; </div>;
} }

View File

@ -17,7 +17,7 @@ export default function Radio({name, value, options, onChange, disabled}) {
function renderOption(opt, i) { function renderOption(opt, i) {
const isSelected = index === i; const isSelected = index === i;
return <label className={"bd-radio-option" + (isSelected ? " bd-radio-selected" : "")}> return <label className={"bd-radio-option" + (isSelected ? " bd-radio-selected" : "")} style={{borderColor: opt.color ?? "transparent"}}>
<input onChange={change} type="radio" name={name} checked={isSelected} value={i} disabled={disabled} /> <input onChange={change} type="radio" name={name} checked={isSelected} value={i} disabled={disabled} />
{/* <span className="bd-radio-button"></span> */} {/* <span className="bd-radio-button"></span> */}
<RadioIcon className="bd-radio-icon" size="24" checked={isSelected} /> <RadioIcon className="bd-radio-icon" size="24" checked={isSelected} />

View File

@ -47,5 +47,5 @@ export function buildSetting(setting) {
if (setting.type == "color") children = <Color {...setting} />; if (setting.type == "color") children = <Color {...setting} />;
if (setting.type == "custom") children = setting.children; if (setting.type == "custom") children = setting.children;
if (!children) return null; if (!children) return null;
return <Item id={setting.id} inline={setting.hasOwnProperty("inline") ? setting.inline : setting.type !== "radio" && setting.type !== "color" && setting.type !== "slider"} key={setting.id} name={setting.name} note={setting.note}>{children}</Item>; return <Item id={setting.id} inline={setting.hasOwnProperty("inline") ? setting.inline : setting.type !== "radio"} key={setting.id} name={setting.name} note={setting.note}>{children}</Item>;
} }