mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-22 16:58:28 +02:00
Improve <details> component (#238)
Co-authored-by: Gregory Schier <gschier1990@gmail.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import { showDialog } from '../lib/dialog';
|
|||||||
import { resolvedModelName } from '../lib/resolvedModelName';
|
import { resolvedModelName } from '../lib/resolvedModelName';
|
||||||
import { Banner } from './core/Banner';
|
import { Banner } from './core/Banner';
|
||||||
import { Checkbox } from './core/Checkbox';
|
import { Checkbox } from './core/Checkbox';
|
||||||
|
import { DetailsBanner } from './core/DetailsBanner';
|
||||||
import { Editor } from './core/Editor/Editor';
|
import { Editor } from './core/Editor/Editor';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
import { Input } from './core/Input';
|
import { Input } from './core/Input';
|
||||||
@@ -174,22 +175,23 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
|
|||||||
);
|
);
|
||||||
case 'accordion':
|
case 'accordion':
|
||||||
return (
|
return (
|
||||||
<Banner key={i} className={classNames('!p-0', disabled && 'opacity-disabled')}>
|
<DetailsBanner
|
||||||
<details>
|
key={i}
|
||||||
<summary className="px-3 py-1.5 text-text-subtle">{input.label}</summary>
|
summary={input.label}
|
||||||
<div className="mb-3 px-3">
|
className={classNames(disabled && 'opacity-disabled')}
|
||||||
<FormInputs
|
>
|
||||||
data={data}
|
<div className="mb-3 px-3">
|
||||||
disabled={disabled}
|
<FormInputs
|
||||||
inputs={input.inputs}
|
data={data}
|
||||||
setDataAttr={setDataAttr}
|
disabled={disabled}
|
||||||
stateKey={stateKey}
|
inputs={input.inputs}
|
||||||
autocompleteFunctions={autocompleteFunctions || false}
|
setDataAttr={setDataAttr}
|
||||||
autocompleteVariables={autocompleteVariables}
|
stateKey={stateKey}
|
||||||
/>
|
autocompleteFunctions={autocompleteFunctions || false}
|
||||||
</div>
|
autocompleteVariables={autocompleteVariables}
|
||||||
</details>
|
/>
|
||||||
</Banner>
|
</div>
|
||||||
|
</DetailsBanner>
|
||||||
);
|
);
|
||||||
case 'banner':
|
case 'banner':
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import slugify from 'slugify';
|
|||||||
import { activeWorkspaceAtom } from '../hooks/useActiveWorkspace';
|
import { activeWorkspaceAtom } from '../hooks/useActiveWorkspace';
|
||||||
import { pluralizeCount } from '../lib/pluralize';
|
import { pluralizeCount } from '../lib/pluralize';
|
||||||
import { invokeCmd } from '../lib/tauri';
|
import { invokeCmd } from '../lib/tauri';
|
||||||
import { Banner } from './core/Banner';
|
|
||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import { Checkbox } from './core/Checkbox';
|
import { Checkbox } from './core/Checkbox';
|
||||||
|
import { DetailsBanner } from './core/DetailsBanner';
|
||||||
import { HStack, VStack } from './core/Stacks';
|
import { HStack, VStack } from './core/Stacks';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -123,19 +123,14 @@ function ExportDataDialogContent({
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<Banner className="!p-0">
|
<DetailsBanner color="secondary" open summary="Extra Settings">
|
||||||
<details open>
|
<Checkbox
|
||||||
<summary className="px-3 py-2">Extra Settings</summary>
|
checked={includePrivateEnvironments}
|
||||||
<div className="px-3 pb-2">
|
onChange={setIncludePrivateEnvironments}
|
||||||
<Checkbox
|
title="Include private environments"
|
||||||
checked={includePrivateEnvironments}
|
help='Environments marked as "sharable" will be exported by default'
|
||||||
onChange={setIncludePrivateEnvironments}
|
/>
|
||||||
title="Include private environments"
|
</DetailsBanner>
|
||||||
help='Environments marked as "sharable" will be exported by default'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
</Banner>
|
|
||||||
<HStack space={2} justifyContent="end">
|
<HStack space={2} justifyContent="end">
|
||||||
<Button className="focus" variant="border" onClick={onHide}>
|
<Button className="focus" variant="border" onClick={onHide}>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { connections } from '../lib/data/connections';
|
|||||||
import { encodings } from '../lib/data/encodings';
|
import { encodings } from '../lib/data/encodings';
|
||||||
import { headerNames } from '../lib/data/headerNames';
|
import { headerNames } from '../lib/data/headerNames';
|
||||||
import { mimeTypes } from '../lib/data/mimetypes';
|
import { mimeTypes } from '../lib/data/mimetypes';
|
||||||
import { Banner } from './core/Banner';
|
|
||||||
import { CountBadge } from './core/CountBadge';
|
import { CountBadge } from './core/CountBadge';
|
||||||
|
import { DetailsBanner } from './core/DetailsBanner';
|
||||||
import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
|
import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
|
||||||
import type { InputProps } from './core/Input';
|
import type { InputProps } from './core/Input';
|
||||||
import type { Pair, PairEditorProps } from './core/PairEditor';
|
import type { Pair, PairEditorProps } from './core/PairEditor';
|
||||||
@@ -35,35 +35,36 @@ export function HeadersEditor({
|
|||||||
return (
|
return (
|
||||||
<div className="@container w-full h-full grid grid-rows-[auto_minmax(0,1fr)]">
|
<div className="@container w-full h-full grid grid-rows-[auto_minmax(0,1fr)]">
|
||||||
{validInheritedHeaders.length > 0 ? (
|
{validInheritedHeaders.length > 0 ? (
|
||||||
<Banner className="!py-0 mb-1.5 border-dashed" color="secondary">
|
<DetailsBanner
|
||||||
<details>
|
color="secondary"
|
||||||
<summary className="py-1.5 text-sm !cursor-default !select-none opacity-70 hover:opacity-100">
|
className="text-sm mb-1.5"
|
||||||
<HStack>
|
summary={
|
||||||
Inherited <CountBadge count={validInheritedHeaders.length} />
|
<HStack>
|
||||||
</HStack>
|
Inherited <CountBadge count={validInheritedHeaders.length} />
|
||||||
</summary>
|
</HStack>
|
||||||
<div className="pb-2">
|
}
|
||||||
{validInheritedHeaders?.map((pair, i) => (
|
>
|
||||||
<PairEditorRow
|
<div className="pb-2">
|
||||||
key={pair.id + '.' + i}
|
{validInheritedHeaders?.map((pair, i) => (
|
||||||
index={i}
|
<PairEditorRow
|
||||||
disabled
|
key={pair.id + '.' + i}
|
||||||
disableDrag
|
index={i}
|
||||||
className="py-1"
|
disabled
|
||||||
onChange={() => {}}
|
disableDrag
|
||||||
onEnd={() => {}}
|
className="py-1"
|
||||||
onMove={() => {}}
|
onChange={() => {}}
|
||||||
pair={ensurePairId(pair)}
|
onEnd={() => {}}
|
||||||
stateKey={null}
|
onMove={() => {}}
|
||||||
nameAutocompleteFunctions
|
pair={ensurePairId(pair)}
|
||||||
nameAutocompleteVariables
|
stateKey={null}
|
||||||
valueAutocompleteFunctions
|
nameAutocompleteFunctions
|
||||||
valueAutocompleteVariables
|
nameAutocompleteVariables
|
||||||
/>
|
valueAutocompleteFunctions
|
||||||
))}
|
valueAutocompleteVariables
|
||||||
</div>
|
/>
|
||||||
</details>
|
))}
|
||||||
</Banner>
|
</div>
|
||||||
|
</DetailsBanner>
|
||||||
) : (
|
) : (
|
||||||
<span />
|
<span />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
|
import { DetailsBanner } from './core/DetailsBanner';
|
||||||
import { FormattedError } from './core/FormattedError';
|
import { FormattedError } from './core/FormattedError';
|
||||||
import { Heading } from './core/Heading';
|
import { Heading } from './core/Heading';
|
||||||
import { VStack } from './core/Stacks';
|
import { VStack } from './core/Stacks';
|
||||||
@@ -17,10 +18,9 @@ export default function RouteError({ error }: { error: unknown }) {
|
|||||||
<FormattedError>
|
<FormattedError>
|
||||||
{message}
|
{message}
|
||||||
{stack && (
|
{stack && (
|
||||||
<details className="mt-3 select-auto text-xs">
|
<DetailsBanner color="secondary" className="mt-3 select-auto text-xs" summary="Stack Trace">
|
||||||
<summary className="!cursor-default !select-none">Stack Trace</summary>
|
|
||||||
<div className="mt-2 text-xs">{stack}</div>
|
<div className="mt-2 text-xs">{stack}</div>
|
||||||
</details>
|
</DetailsBanner>
|
||||||
)}
|
)}
|
||||||
</FormattedError>
|
</FormattedError>
|
||||||
<VStack space={2}>
|
<VStack space={2}>
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ export function Banner({ children, className, color }: BannerProps) {
|
|||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
|
color && 'bg-surface',
|
||||||
`x-theme-banner--${color}`,
|
`x-theme-banner--${color}`,
|
||||||
'border border-border bg-surface',
|
'border border-border border-dashed',
|
||||||
'px-4 py-3 rounded-lg select-auto',
|
'px-4 py-2 rounded-lg select-auto',
|
||||||
'overflow-auto text-text',
|
'overflow-auto text-text',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
31
src-web/components/core/DetailsBanner.tsx
Normal file
31
src-web/components/core/DetailsBanner.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import type { HTMLAttributes, ReactNode } from 'react';
|
||||||
|
import type { BannerProps } from './Banner';
|
||||||
|
import { Banner } from './Banner';
|
||||||
|
|
||||||
|
interface Props extends HTMLAttributes<HTMLDetailsElement> {
|
||||||
|
summary: ReactNode;
|
||||||
|
color?: BannerProps['color'];
|
||||||
|
open?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DetailsBanner({ className, color, summary, children, ...extraProps }: Props) {
|
||||||
|
return (
|
||||||
|
<Banner color={color} className={className}>
|
||||||
|
<details className="group list-none" {...extraProps}>
|
||||||
|
<summary className="!cursor-default !select-none list-none flex items-center gap-2 focus:outline-none opacity-70 hover:opacity-100 focus:opacity-100">
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'transition-transform',
|
||||||
|
'group-open:rotate-90',
|
||||||
|
'w-0 h-0 border-t-[0.3em] border-b-[0.3em] border-l-[0.5em] border-r-0',
|
||||||
|
'border-t-transparent border-b-transparent border-l-text-subtle',
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
{summary}
|
||||||
|
</summary>
|
||||||
|
{children}
|
||||||
|
</details>
|
||||||
|
</Banner>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user