style tweaks

This commit is contained in:
Felix Roos
2026-01-19 23:00:14 +01:00
parent 8ec1d4d034
commit 38b7bcb3d2
12 changed files with 62 additions and 65 deletions
@@ -13,16 +13,13 @@ export function SpecialActionButton(props) {
const { className, ...buttonProps } = props;
return (
<ActionButton
{...buttonProps}
className={cx('bg-background p-2 max-w-[300px] rounded-md hover:opacity-50', className)}
/>
<ActionButton {...buttonProps} className={cx('bg-background p-2 max-w-[300px] hover:opacity-50', className)} />
);
}
export function ActionInput({ label, className, ...props }) {
return (
<label className={cx('inline-flex items-center cursor-pointer', className)}>
<label className={cx('inline-flex items-center cursor-pointer ', className)}>
<input {...props} className="sr-only peer" />
<span className="inline-flex items-center peer-hover:opacity-50">{label}</span>
@@ -35,7 +32,7 @@ export function SpecialActionInput({ className, ...props }) {
<ActionInput
{...props}
className={className}
label={<span className="bg-background p-2 max-w-[300px] rounded-md">{props.label}</span>}
label={<span className="bg-background p-2 max-w-[300px]">{props.label}</span>}
/>
);
}
@@ -1,4 +1,4 @@
import { Textbox } from '../textbox/Textbox';
import { Textbox } from '@src/repl/components/panel/SettingsTab';
import cx from '@src/cx.mjs';
function IncButton({ children, className, ...buttonProps }) {
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { SelectInput } from './SelectInput';
import { SelectInputDuplicate } from '@src/repl/components/panel/SettingsTab';
import { getAudioDevices } from '@strudel/webaudio';
const initdevices = new Map();
@@ -29,7 +29,7 @@ export function AudioDeviceSelector({ audioDeviceName, onChange, isDisabled }) {
options.set(deviceName, deviceName);
});
return (
<SelectInput
<SelectInputDuplicate
isDisabled={isDisabled}
options={options}
onClick={onClick}
@@ -1,6 +1,6 @@
import React from 'react';
import { audioEngineTargets } from '../../../settings.mjs';
import { SelectInput } from './SelectInput';
import { SelectInputDuplicate } from '@src/repl/components/panel/SettingsTab';
// Allows the user to select an audio interface for Strudel to play through
export function AudioEngineTargetSelector({ target, onChange, isDisabled }) {
@@ -12,8 +12,8 @@ export function AudioEngineTargetSelector({ target, onChange, isDisabled }) {
[audioEngineTargets.osc, audioEngineTargets.osc],
]);
return (
<div className=" flex flex-col gap-1">
<SelectInput isDisabled={isDisabled} options={options} value={target} onChange={onTargetChange} />
<div className="flex flex-col gap-1">
<SelectInputDuplicate isDisabled={isDisabled} options={options} value={target} onChange={onTargetChange} />
{target === audioEngineTargets.osc && (
<div>
<p className="text-sm italic">
@@ -1,10 +1,7 @@
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
import cx from '@src/cx.mjs';
import NumberInput from '@src/repl/components/NumberInput';
import { useEffect, useState } from 'react';
import { Textbox } from '../textbox/Textbox';
import { useState } from 'react';
import { Textbox } from '@src/repl/components/panel/SettingsTab';
import { getAudioContext } from '@strudel/webaudio';
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
function Checkbox({ label, value, onChange, disabled = false }) {
return (
+1 -1
View File
@@ -13,7 +13,7 @@ export function ButtonGroup({ value, onChange, items }) {
// i === 0 && 'rounded-l-md',
// i === arr.length - 1 && 'rounded-r-md',
// value === key ? 'bg-background' : 'bg-lineHighlight',
value === key ? 'border-foreground' : 'border-transparent',
value === key ? 'border-foreground' : 'border-background',
)}
>
{label.toLowerCase()}
@@ -18,7 +18,7 @@ import { Pagination } from '../pagination/Pagination.jsx';
import { useState } from 'react';
import { useDebounce } from '../usedebounce.jsx';
import cx from '@src/cx.mjs';
import { Textbox } from '../textbox/Textbox.jsx';
import { Textbox } from '@src/repl/components/panel/SettingsTab.jsx';
export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
@@ -1,7 +1,7 @@
import { memo, useEffect, useMemo, useState, Fragment } from 'react';
import jsdocJson from '../../../../../doc.json';
import { Textbox } from '../textbox/Textbox';
import { Textbox } from '@src/repl/components/panel/SettingsTab';
const isValid = ({ name, description }) => name && !name.startsWith('_') && !!description;
@@ -1,20 +0,0 @@
import React from 'react';
// value: ?ID, options: Map<ID, any>, onChange: ID => null, onClick: event => void, isDisabled: boolean
export function SelectInput({ value, options, onChange, onClick, isDisabled }) {
return (
<select
disabled={isDisabled}
onClick={onClick}
className="p-2 bg-background rounded-md text-foreground border-foreground"
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
>
{options.size == 0 && <option value={value}>{`${value ?? 'select an option'}`}</option>}
{Array.from(options.keys()).map((id) => (
<option key={id} className="bg-background" value={id}>
{options.get(id)}
</option>
))}
</select>
);
}
@@ -1,6 +1,5 @@
import { defaultSettings, settingsMap, useSettings } from '../../../settings.mjs';
import { themes } from '@strudel/codemirror';
import { Textbox } from '../textbox/Textbox.jsx';
import { confirmAndReloadPage, isUdels } from '../../util.mjs';
import { ButtonGroup } from './Forms.jsx';
import { AudioDeviceSelector } from './AudioDeviceSelector.jsx';
@@ -10,22 +9,60 @@ import { DEFAULT_MAX_POLYPHONY, setMaxPolyphony, setMultiChannelOrbits } from '@
import { SpecialActionButton } from '../button/action-button.jsx';
import { ImportPrebakeScriptButton } from './ImportPrebakeScriptButton.jsx';
function cx(...classes) {
// : Array<string | undefined>
return classes.filter(Boolean).join(' ');
}
const inputClass =
'bg-background text-sm border rounded-0 text-foreground border-foreground placeholder-foreground focus:outline-none focus:ring-0 focus:border-foreground';
export function Textbox({ onChange, className, ...inputProps }) {
return (
<input className={cx('p-2', inputClass, className)} onChange={(e) => onChange(e.target.value)} {...inputProps} />
);
}
function Checkbox({ label, value, onChange, disabled = false }) {
return (
<label>
<input disabled={disabled} type="checkbox" checked={value} onChange={onChange} />
<input
className={cx(
'bg-background text-sm border border-foreground focus:outline-none focus:ring-0 focus:border-foreground',
)}
disabled={disabled}
type="checkbox"
checked={value}
onChange={onChange}
/>
{' ' + label}
</label>
);
}
function SelectInput({ value, options, onChange }) {
// value: ?ID, options: Map<ID, any>, onChange: ID => null, onClick: event => void, isDisabled: boolean
export function SelectInputDuplicate({ value, options, onChange, onClick, isDisabled }) {
return (
<select
className="p-2 bg-background rounded-md text-foreground border-foreground"
value={value}
disabled={isDisabled}
onClick={onClick}
className={cx('p-2', inputClass)}
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
>
{options.size == 0 && <option value={value}>{`${value ?? 'select an option'}`}</option>}
{Array.from(options.keys()).map((id) => (
<option key={id} className="bg-background" value={id}>
{options.get(id)}
</option>
))}
</select>
);
}
function SelectInput({ value, options, onChange }) {
return (
<select className={cx('p-2', inputClass)} value={value} onChange={(e) => onChange(e.target.value)}>
{Object.entries(options).map(([k, label]) => (
<option key={k} className="bg-background" value={k}>
{label}
@@ -37,9 +74,9 @@ function SelectInput({ value, options, onChange }) {
function NumberSlider({ value, onChange, step = 1, ...rest }) {
return (
<div className="flex space-x-2 gap-1">
<div className="flex space-x-2 gap-1 overflow-hidden">
<input
className="p-2 grow"
className="p-2 grow accent-foreground"
type="range"
value={value}
step={step}
@@ -50,7 +87,7 @@ function NumberSlider({ value, onChange, step = 1, ...rest }) {
type="number"
value={value}
step={step}
className="w-16 bg-background rounded-md"
className={cx('w-16', inputClass)}
onChange={(e) => onChange(Number(e.target.value))}
/>
</div>
@@ -60,7 +97,7 @@ function NumberSlider({ value, onChange, step = 1, ...rest }) {
function FormItem({ label, children, sublabel }) {
return (
<div className="grid gap-2">
<label>{label}</label>
<label className="text-sm">{label}</label>
{children}
</div>
);
@@ -178,7 +215,7 @@ export function SettingsTab({ started }) {
<FormItem label="Theme">
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
</FormItem>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 font-sans">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormItem label="Font Family">
<SelectInput
options={fontFamilyOptions}
@@ -5,7 +5,7 @@ import { useMemo, useRef, useState } from 'react';
import { settingsMap, soundFilterType, useSettings } from '../../../settings.mjs';
import { ButtonGroup } from './Forms.jsx';
import ImportSoundsButton from './ImportSoundsButton.jsx';
import { Textbox } from '../textbox/Textbox.jsx';
import { Textbox } from '@src/repl/components/panel/SettingsTab.jsx';
import { ActionButton } from '../button/action-button.jsx';
import { confirmDialog } from '@src/repl/util.mjs';
import { clearIDB, userSamplesDBConfig } from '@src/repl/idbutils.mjs';
@@ -1,14 +0,0 @@
import cx from '@src/cx.mjs';
export function Textbox({ onChange, className, ...inputProps }) {
return (
<input
className={cx(
'p-2 bg-background rounded-md border-foreground text-foreground placeholder-foreground',
className,
)}
onChange={(e) => onChange(e.target.value)}
{...inputProps}
/>
);
}