make it crunchier: border borders, less padding

This commit is contained in:
Felix Roos
2026-01-21 01:31:25 +01:00
parent 84e4dde3d7
commit cb46dd7840
13 changed files with 96 additions and 93 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ export const settings = {
background: '#222',
lineBackground: '#22222299',
foreground: '#fff',
muted: '#ffffff50',
muted: '#8a919966',
caret: '#ffcc00',
selection: 'rgba(128, 203, 196, 0.5)',
selectionMatch: '#036dd626',
+1 -1
View File
@@ -8,7 +8,7 @@ export function Code(Props) {
return (
<section
className={'text-gray-100 cursor-text pb-0 overflow-auto grow'}
className={'text-gray-100 cursor-text pb-0 overflow-auto grow z-10'}
id="code"
ref={(el) => {
containerRef.current = el;
+1 -1
View File
@@ -16,7 +16,7 @@ export function Header({ context, isEmbedded = false }) {
<header
id="header"
className={cx(
'flex-none text-black z-[100] text-sm select-none min-h-10',
'border-b border-muted flex-none text-black z-[100] text-sm select-none min-h-10',
!isZen && !isEmbedded && 'bg-lineHighlight',
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full justify-between',
'flex items-center',
@@ -2,7 +2,7 @@ import cx from '@src/cx.mjs';
export function ActionButton({ children, label, labelIsHidden, className, ...buttonProps }) {
return (
<button className={cx('hover:opacity-50 text-nowrap w-fit text-sm ', className)} title={label} {...buttonProps}>
<button className={cx('hover:opacity-50 text-nowrap w-fit', className)} title={label} {...buttonProps}>
{labelIsHidden !== true && label}
{children}
</button>
@@ -7,8 +7,10 @@ export function ConsoleTab() {
const log = useStore($strudel_log_history);
const { fontFamily } = useSettings();
return (
<div id="console-tab" className="break-all w-full text-sm p-2 h-full" style={{ fontFamily }}>
<div className="bg-background h-full w-full overflow-auto space-y-1 p-2 rounded-md">
<div id="console-tab" className="break-all w-full h-full" style={{ fontFamily }}>
<div className="h-full w-full overflow-auto space-y-1 p-2 rounded-md">
{' '}
{/* bg-background */}
{log.map((l, i) => {
const message = linkify(l.message);
const color = l.data?.hap?.value?.color;
@@ -45,7 +45,7 @@ export default function ExportTab(Props) {
return (
<>
<div className="text-foreground w-full p-4 space-y-4">
<div className="text-foreground w-full space-y-4 p-4">
<FormItem label="File name" disabled={exporting}>
<Textbox
onBlur={(e) => {
+1 -1
View File
@@ -2,7 +2,7 @@ import cx from '@src/cx.mjs';
export function ButtonGroup({ value, onChange, items }) {
return (
<div className="flex max-w-lg space-x-0 text-sm">
<div className="flex max-w-lg space-x-0">
{Object.entries(items).map(([key, label], i, arr) => (
<button
key={key}
+12 -9
View File
@@ -19,7 +19,7 @@ function PanelCloseButton() {
isPanelOpen && (
<button
onClick={() => setIsPanelOpened(false)}
className={cx('px-4 py-2 text-foreground hover:opacity-50')}
className={cx('px-4 py-1 text-foreground hover:opacity-50')}
aria-label="Close Menu"
>
<XMarkIcon className="w-6 h-6" />
@@ -34,15 +34,15 @@ export function HorizontalPanel({ context }) {
<PanelNav
className={cx(
isPanelOpen ? `min-h-[360px] max-h-[360px]` : 'min-h-10 max-h-10',
'overflow-hidden flex flex-col relative ',
'overflow-hidden flex flex-col relative',
)}
>
<div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center">
<div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center border-b border-muted">
<Tabs setTab={setTab} tab={tab} />
<PanelCloseButton />
</div>
{isPanelOpen && (
<div className="flex h-full overflow-auto w-full">
<div className="w-full h-full overflow-hidden">
<PanelContent context={context} tab={tab} />
</div>
)}
@@ -59,10 +59,13 @@ export function VerticalPanel({ context }) {
return (
<PanelNav
settings={settings}
className={cx(isPanelOpen ? `min-w-[min(600px,100vw)] max-w-[min(600px,80vw)]` : 'min-w-12 max-w-12')}
className={cx(
'border-l border-muted',
isPanelOpen ? `min-w-[min(600px,100vw)] max-w-[min(600px,80vw)]` : 'min-w-12 max-w-12',
)}
>
<div className={cx('flex flex-col h-full')}>
<div className="flex justify-between w-full ">
<div className="flex justify-between w-full border-b border-muted">
<Tabs setTab={setTab} tab={tab} />
<PanelCloseButton />
</div>
@@ -134,7 +137,7 @@ function PanelTab({ label, isSelected, onClick }) {
<button
onClick={onClick}
className={cx(
'h-8 px-2 text-sm text-foreground cursor-pointer hover:opacity-50 flex items-center space-x-1 border-b',
'h-8 px-2 text-sm text-foreground cursor-pointer hover:opacity-50 flex items-center space-x-1 border-b-2',
isSelected ? 'border-foreground' : 'border-transparent',
)}
>
@@ -146,7 +149,7 @@ function PanelTab({ label, isSelected, onClick }) {
function Tabs({ className }) {
const { isPanelOpen, activeFooter: tab } = useSettings();
return (
<div className={cx('flex select-none max-w-full overflow-auto items-center', className)}>
<div className={cx('w-full flex select-none max-w-full overflow-auto items-center', className)}>
{Object.keys(tabNames).map((key) => {
const val = tabNames[key];
return <PanelTab key={key} isSelected={tab === val && isPanelOpen} label={key} onClick={() => setTab(val)} />;
@@ -164,7 +167,7 @@ export function PanelToggle({ isEmbedded, isZen }) {
<button
title="share"
className={cx(
'absolute top-0 right-3 rounded-0 px-2 py-2 bg-background z-[1000] cursor-pointer hover:opacity-80 flex justify-center items-center space-x-1 text-foreground ',
'absolute top-0.5 right-3 rounded-0 px-2 py-2 bg-background z-[1000] cursor-pointer hover:opacity-80 flex justify-center items-center space-x-1 text-foreground ',
isPanelOpen && 'hidden',
)}
onClick={() => setIsPanelOpened(!isPanelOpen)}
@@ -43,7 +43,7 @@ function PatternButton({ showOutline, onClick, pattern, showHiglight }) {
className={cx(
'mr-4 hover:opacity-50 cursor-pointer block',
showOutline && 'outline outline-1',
showHiglight && 'bg-selection',
showHiglight && 'ring-selection',
)}
onClick={onClick}
>
@@ -57,7 +57,7 @@ function PatternButtons({ patterns, activePattern, onClick, started }) {
const viewingPatternData = parseJSON(viewingPatternStore);
const viewingPatternID = viewingPatternData.id;
return (
<div className="">
<div className="p-2">
{Object.values(patterns)
.reverse()
.map((pattern) => {
@@ -124,71 +124,68 @@ export function PatternsTab({ context }) {
}, [search, viewingPatternStore]);
return (
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
<div className="w-full flex">
<Textbox className="w-full" placeholder="Search" value={search} onChange={setSearch} />
<div className="w-full h-full text-foreground flex flex-col overflow-hidden">
<Textbox className="w-full border-0" placeholder="Search" value={search} onChange={setSearch} />
<div className="px-2 shrink-0 py-2 space-x-4 flex max-w-full overflow-x-auto border-y border-muted">
<ActionButton
label="new"
onClick={() => {
const { data } = userPattern.createAndAddToDB();
updateCodeWindow(context, data);
}}
/>
<ActionButton
label="duplicate"
onClick={() => {
const { data } = userPattern.duplicate(viewingPatternData);
updateCodeWindow(context, data);
}}
/>
<ActionButton
label="delete"
onClick={() => {
const { data } = userPattern.delete(viewingPatternID);
updateCodeWindow(context, { ...data, collection: userPattern.collection });
}}
/>
<label className="hover:opacity-50 cursor-pointer">
<input
style={{ display: 'none' }}
type="file"
multiple
accept="text/plain,text/x-markdown,application/json"
onChange={(e) => importPatterns(e.target.files)}
/>
import
</label>
<ActionButton label="export" onClick={exportPatterns} />
<ActionButton
label="delete-all"
onClick={() => {
const { data } = userPattern.clearAll();
updateCodeWindow(context, data);
}}
/>
</div>
<div className="flex flex-col gap-2 flex-grow overflow-hidden h-full pb-2 ">
<div className="pr-4 space-x-4 flex max-w-full overflow-x-auto">
<ActionButton
label="new"
onClick={() => {
const { data } = userPattern.createAndAddToDB();
updateCodeWindow(context, data);
}}
/>
<ActionButton
label="duplicate"
onClick={() => {
const { data } = userPattern.duplicate(viewingPatternData);
updateCodeWindow(context, data);
}}
/>
<ActionButton
label="delete"
onClick={() => {
const { data } = userPattern.delete(viewingPatternID);
updateCodeWindow(context, { ...data, collection: userPattern.collection });
}}
/>
<label className="hover:opacity-50 cursor-pointer">
<input
style={{ display: 'none' }}
type="file"
multiple
accept="text/plain,text/x-markdown,application/json"
onChange={(e) => importPatterns(e.target.files)}
/>
import
</label>
<ActionButton label="export" onClick={exportPatterns} />
<ActionButton
label="delete-all"
onClick={() => {
const { data } = userPattern.clearAll();
updateCodeWindow(context, data);
}}
/>
</div>
<div className="overflow-auto">
{/* bg-background */}
{/* {patternFilter === patternFilterName.user && ( */}
<PatternButtons
onClick={(id) => {
updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart);
<div className="overflow-auto h-full bg-background p-2">
{/* {patternFilter === patternFilterName.user && ( */}
<PatternButtons
onClick={(id) => {
updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart);
if (context.started && activePattern === id) {
context.handleEvaluate();
}
}}
patterns={visiblePatterns}
started={context.started}
activePattern={activePattern}
viewingPatternID={viewingPatternID}
/>
{/* )} */}
</div>
if (context.started && activePattern === id) {
context.handleEvaluate();
}
}}
patterns={visiblePatterns}
started={context.started}
activePattern={activePattern}
viewingPatternID={viewingPatternID}
/>
{/* )} */}
</div>
</div>
);
@@ -112,11 +112,12 @@ export const Reference = memo(function Reference() {
}, [selectedFunction]);
return (
<div className="flex h-full w-full p-2 overflow-hidden">
<div className="h-full text-foreground flex flex-col gap-3 w-1/3 ">
<div className="flex h-full w-full overflow-hidden">
<div className="h-full text-foreground flex flex-col w-1/3 border-r border-muted">
{/* bg-background */}
<div className="w-full flex">
<Textbox
className="w-full"
className="w-full border-0 border-b border-muted"
placeholder="Search"
value={search}
onChange={(e) => {
@@ -128,14 +129,14 @@ export const Reference = memo(function Reference() {
{selectedTag && (
<div className="w-72">
<span
className="text-foreground border border-muted px-1 py-0.5 my-2 cursor-pointer font-sans"
className="text-foreground border border-muted border-t-0 border-l-0 px-1 py-0.5 my-2 cursor-pointer font-sans"
onClick={onSearchTagFilterClick}
>
{selectedTag}
</span>
</div>
)}
<div className="flex flex-col h-full overflow-y-auto gap-1.5 bg-background bg-opacity-50">
<div className="flex flex-col h-full py-2 overflow-y-auto gap-1.5 bg-opacity-50">
{searchVisibleFunctions.map((entry, i) => (
<Fragment key={`entry-${entry.name}`}>
<a
@@ -161,7 +162,7 @@ export const Reference = memo(function Reference() {
className="break-normal flex-col overflow-y-auto overflow-x-hidden p-2 flex relative"
id="reference-container"
>
<div className="prose dark:prose-invert min-w-full px-1 ">
<div className="prose dark:prose-invert min-w-full px-1 text-sm">
<h2>API Reference</h2>
<p className="font-sans text-md">
This is the long list of functions you can use. Remember that you don't need to remember all of those and
@@ -154,7 +154,7 @@ export function SettingsTab({ started }) {
const shouldAlwaysSync = isUdels();
const canChangeAudioDevice = AudioContext.prototype.setSinkId != null;
return (
<div className="text-foreground p-4 space-y-4 w-full" style={{ fontFamily }}>
<div className="p-4 text-foreground space-y-4 w-full" style={{ fontFamily }}>
{canChangeAudioDevice && (
<FormItem label="Audio Output Device">
<AudioDeviceSelector
@@ -77,10 +77,10 @@ export function SoundsTab() {
numRef.current = 0;
});
return (
<div id="sounds-tab" className="px-4 flex gap-2 flex-col w-full h-full text-foreground">
<Textbox placeholder="Search" value={search} onChange={(v) => setSearch(v)} />
<div id="sounds-tab" className="flex flex-col w-full h-full text-foreground">
<Textbox placeholder="Search" className="border-0" value={search} onChange={(v) => setSearch(v)} />
<div className=" flex shrink-0 flex-wrap">
<div className="flex shrink-0 flex-wrap border-y border-muted">
<ButtonGroup
value={soundsFilter}
onChange={(value) => settingsMap.setKey('soundsFilter', value)}
@@ -114,7 +114,7 @@ export function SoundsTab() {
/>
)}
<div className="min-h-0 max-h-full grow overflow-auto text-sm break-normal bg-background p-2 rounded-md">
<div className="min-h-0 max-h-full grow overflow-auto break-normal p-2">
{soundEntries.map(([name, { data, onTrigger }]) => {
return (
<span
@@ -6,7 +6,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
export function WelcomeTab({ context }) {
const { fontFamily } = useSettings();
return (
<div className="prose dark:prose-invert min-w-full pt-2 font-sans pb-8 px-4 " style={{ fontFamily }}>
<div className="prose dark:prose-invert min-w-full py-4 font-sans px-4 text-sm" style={{ fontFamily }}>
<h3>welcome</h3>
<p>
You have found <span className="underline">strudel</span>, a new live coding platform to write dynamic music