mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-22 09:29:16 +01:00
More subtle layout tweaks
This commit is contained in:
@@ -52,7 +52,7 @@ export const Button = forwardRef(function Button<T extends ElementType>(
|
||||
justify === 'center' && 'justify-center',
|
||||
size === 'md' && 'h-10 px-4',
|
||||
size === 'sm' && 'h-8 px-3 text-sm',
|
||||
size === 'xs' && 'h-6 px-3 text-xs',
|
||||
size === 'xs' && 'h-7 px-2.5 text-sm',
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
|
||||
.cm-editor {
|
||||
@apply w-full block text-[0.85rem] bg-gray-25;
|
||||
@apply bg-background w-full block text-[0.85rem];
|
||||
|
||||
&.cm-focused {
|
||||
outline: none !important;
|
||||
@@ -70,7 +70,7 @@
|
||||
}
|
||||
|
||||
.cm-editor .cm-gutters {
|
||||
@apply bg-gray-25 border-0 text-gray-200;
|
||||
@apply bg-background border-0 text-gray-200;
|
||||
}
|
||||
|
||||
.cm-editor .cm-gutterElement {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Compartment, EditorState } from '@codemirror/state';
|
||||
import { keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view';
|
||||
import classnames from 'classnames';
|
||||
import { EditorView } from 'codemirror';
|
||||
import type { HTMLAttributes } from 'react';
|
||||
import type { CSSProperties, HTMLAttributes } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import './Editor.css';
|
||||
import { baseExtensions, getLanguageExtension, multiLineExtensions } from './extensions';
|
||||
@@ -13,6 +13,7 @@ import { singleLineExt } from './singleLine';
|
||||
export interface EditorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
||||
height?: 'auto' | 'full';
|
||||
contentType?: string;
|
||||
backgroundColor?: string;
|
||||
autoFocus?: boolean;
|
||||
valueKey?: string | number;
|
||||
defaultValue?: string;
|
||||
@@ -26,6 +27,7 @@ export interface EditorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onCha
|
||||
export default function Editor({
|
||||
height,
|
||||
contentType,
|
||||
backgroundColor,
|
||||
autoFocus,
|
||||
placeholder,
|
||||
valueKey,
|
||||
@@ -100,6 +102,7 @@ export default function Editor({
|
||||
height === 'auto' ? 'cm-auto-height' : 'cm-full-height',
|
||||
singleLine ? 'cm-singleline' : 'cm-multiline',
|
||||
)}
|
||||
data-color-background="var(--color-gray-50)"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import classnames from 'classnames';
|
||||
import { useRequestUpdate, useSendRequest } from '../hooks/useRequest';
|
||||
import type { HttpRequest } from '../lib/models';
|
||||
import { Button } from './Button';
|
||||
import { Divider } from './Divider';
|
||||
import Editor from './Editor/Editor';
|
||||
import { ScrollArea } from './ScrollArea';
|
||||
import { HStack } from './Stacks';
|
||||
@@ -18,10 +17,12 @@ export function RequestPane({ fullHeight, request, className }: Props) {
|
||||
const updateRequest = useRequestUpdate(request ?? null);
|
||||
const sendRequest = useSendRequest(request ?? null);
|
||||
return (
|
||||
<div className={classnames(className, 'grid grid-rows-[auto_auto_minmax(0,1fr)] grid-cols-1')}>
|
||||
<div>
|
||||
<div
|
||||
className={classnames(className, 'py-2 grid grid-rows-[auto_auto_minmax(0,1fr)] grid-cols-1')}
|
||||
>
|
||||
<div className="pl-2">
|
||||
<UrlBar
|
||||
className="bg-transparent border-0 mb-1"
|
||||
className="border-0 mb-1"
|
||||
key={request.id}
|
||||
method={request.method}
|
||||
url={request.url}
|
||||
@@ -30,9 +31,7 @@ export function RequestPane({ fullHeight, request, className }: Props) {
|
||||
onUrlChange={(url) => updateRequest.mutate({ url })}
|
||||
sendRequest={sendRequest.mutate}
|
||||
/>
|
||||
<div className="mx-2">
|
||||
<Divider />
|
||||
</div>
|
||||
{/*<Divider />*/}
|
||||
</div>
|
||||
{/*<Divider className="mb-2" />*/}
|
||||
<ScrollArea className="max-w-full pb-2 mx-2">
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import classnames from 'classnames';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useDeleteAllResponses, useDeleteResponse, useResponses } from '../hooks/useResponses';
|
||||
import { Button } from './Button';
|
||||
import { Divider } from './Divider';
|
||||
import { Dropdown } from './Dropdown';
|
||||
import Editor from './Editor/Editor';
|
||||
import { Icon } from './Icon';
|
||||
import { IconButton } from './IconButton';
|
||||
import { ScrollArea } from './ScrollArea';
|
||||
import { HStack } from './Stacks';
|
||||
|
||||
interface Props {
|
||||
@@ -45,23 +42,23 @@ export function ResponsePane({ requestId, className }: Props) {
|
||||
}, [response?.body, contentType]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
className,
|
||||
'max-h-full h-full grid grid-rows-[auto_auto_minmax(0,1fr)] grid-cols-1',
|
||||
)}
|
||||
>
|
||||
{/*<HStack as={WindowDragRegion} items="center" className="pl-1.5 pr-1">*/}
|
||||
{/*</HStack>*/}
|
||||
{response?.error && (
|
||||
<div className="text-white bg-red-500 px-2 py-1 rounded">{response.error}</div>
|
||||
)}
|
||||
{response && (
|
||||
<>
|
||||
<div>
|
||||
<div className="p-2">
|
||||
<div
|
||||
className={classnames(
|
||||
className,
|
||||
'max-h-full h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1 bg-gray-50/50 rounded-md',
|
||||
)}
|
||||
>
|
||||
{/*<HStack as={WindowDragRegion} items="center" className="pl-1.5 pr-1">*/}
|
||||
{/*</HStack>*/}
|
||||
{response?.error && (
|
||||
<div className="text-white bg-red-500 px-2 py-1 rounded">{response.error}</div>
|
||||
)}
|
||||
{response && (
|
||||
<>
|
||||
<HStack
|
||||
items="center"
|
||||
className="italic text-gray-500 text-sm w-full mb-1 flex-shrink-0 pl-2"
|
||||
className="italic text-gray-500 text-sm w-full mb-1 flex-shrink-0 pl-2 py-1"
|
||||
>
|
||||
<div className="whitespace-nowrap">
|
||||
{response.status}
|
||||
@@ -104,43 +101,27 @@ export function ResponsePane({ requestId, className }: Props) {
|
||||
</Dropdown>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<div className="px-2">
|
||||
<Divider />
|
||||
</div>
|
||||
</div>
|
||||
<ScrollArea className="max-w-full pb-2 mx-2">
|
||||
<HStack className="mt-2 hide-scrollbar" space={1}>
|
||||
{['Preview', 'Headers', 'Cookies', 'Timing'].map((label, i) => (
|
||||
<Button
|
||||
key={label}
|
||||
size="xs"
|
||||
color={i === 0 && 'gray'}
|
||||
className={i !== 0 && 'opacity-50 hover:opacity-60'}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
))}
|
||||
</HStack>
|
||||
</ScrollArea>
|
||||
|
||||
{viewMode === 'pretty' && contentForIframe !== null ? (
|
||||
<div className="pl-2">
|
||||
<iframe
|
||||
title="Response preview"
|
||||
srcDoc={contentForIframe}
|
||||
sandbox="allow-scripts allow-same-origin"
|
||||
className="h-full w-full rounded-lg"
|
||||
{viewMode === 'pretty' && contentForIframe !== null ? (
|
||||
<div className="px-2 pb-2">
|
||||
<iframe
|
||||
title="Response preview"
|
||||
srcDoc={contentForIframe}
|
||||
sandbox="allow-scripts allow-same-origin"
|
||||
className="h-full w-full rounded-md border border-gray-100/20"
|
||||
/>
|
||||
</div>
|
||||
) : response?.body ? (
|
||||
<Editor
|
||||
backgroundColor="red"
|
||||
valueKey={`${contentType}:${response.body}`}
|
||||
defaultValue={response?.body}
|
||||
contentType={contentType}
|
||||
/>
|
||||
</div>
|
||||
) : response?.body ? (
|
||||
<Editor
|
||||
valueKey={`${contentType}:${response.body}`}
|
||||
defaultValue={response?.body}
|
||||
contentType={contentType}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,21 +23,24 @@ export function Sidebar({ className, activeRequestId, workspaceId, requests, ...
|
||||
const { toggleTheme } = useTheme();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
return (
|
||||
<div className={classnames(className, 'w-52 bg-gray-50 h-full px-2')} {...props}>
|
||||
<HStack as={WindowDragRegion} items="center" className="py-2" justify="end">
|
||||
<div
|
||||
className={classnames(className, 'w-52 bg-gray-50 h-full border-gray-100/50 relative z-10')}
|
||||
{...props}
|
||||
>
|
||||
<HStack as={WindowDragRegion} items="center" justify="end">
|
||||
<Dialog wide open={open} onOpenChange={setOpen} title="Edit Headers">
|
||||
<HeaderEditor />
|
||||
<Button className="ml-auto mt-5" color="primary" onClick={() => setOpen(false)}>
|
||||
Save
|
||||
</Button>
|
||||
</Dialog>
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon="camera"
|
||||
onClick={() => {
|
||||
setOpen((v) => !v);
|
||||
}}
|
||||
/>
|
||||
{/*<IconButton*/}
|
||||
{/* size="sm"*/}
|
||||
{/* icon="camera"*/}
|
||||
{/* onClick={() => {*/}
|
||||
{/* setOpen((v) => !v);*/}
|
||||
{/* }}*/}
|
||||
{/*/>*/}
|
||||
<IconButton size="sm" icon="sun" onClick={toggleTheme} />
|
||||
<IconButton
|
||||
size="sm"
|
||||
@@ -47,7 +50,7 @@ export function Sidebar({ className, activeRequestId, workspaceId, requests, ...
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
<VStack as="ul" className="pb-3" space={1}>
|
||||
<VStack as="ul" className="py-3 px-2" space={1}>
|
||||
{requests.map((r) => (
|
||||
<SidebarItem key={r.id} request={r} active={r.id === activeRequestId} />
|
||||
))}
|
||||
@@ -63,7 +66,7 @@ function SidebarItem({ request, active }: { request: HttpRequest; active: boolea
|
||||
as={Link}
|
||||
to={`/workspaces/${request.workspaceId}/requests/${request.id}`}
|
||||
className={classnames('w-full', active && 'bg-gray-500/[0.1] text-gray-900')}
|
||||
size="sm"
|
||||
size="xs"
|
||||
justify="start"
|
||||
>
|
||||
{request.name}
|
||||
|
||||
@@ -7,7 +7,7 @@ export function WindowDragRegion({ className, ...props }: Props) {
|
||||
return (
|
||||
<div
|
||||
data-tauri-drag-region
|
||||
className={classnames(className, 'w-full h-8 flex-shrink-0 box-content')}
|
||||
className={classnames(className, 'w-full h-10 flex-shrink-0')}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user