Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Textarea } from '@/components/ui/textarea';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { FIELD_ACTION_CLASS } from './collapse';

export interface AiAssistActionStrings {
trigger: string;
Expand Down Expand Up @@ -100,14 +101,17 @@ export function AiAssistAction({
<Tooltip>
<TooltipTrigger asChild>
<PopoverTrigger asChild>
<button
<Button
type="button"
variant="ghost"
size="3xs"
icon
aria-label={text.trigger}
disabled={disabled}
className="grid size-7 place-items-center rounded-lg text-foreground-subtle transition hover:bg-surface-overlay hover:text-foreground disabled:pointer-events-none disabled:opacity-50"
className={FIELD_ACTION_CLASS}
>
<Sparkles size={12} />
</button>
<Sparkles />
</Button>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent>{text.tooltip}</TooltipContent>
Expand Down
11 changes: 8 additions & 3 deletions packages/apollo-wind/src/components/ui/field-actions/collapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@

/** Hidden once collapsed, such as an action's text. */
export const COLLAPSED_HIDDEN = '@max-[259px]:hidden';
/** The tighter padding of an action collapsed to its icon. */
export const COLLAPSED_ICON_PADDING = '@max-[259px]:px-1.5';
/** Shown only once collapsed. */
export const COLLAPSED_ONLY = 'hidden @max-[259px]:block';
export const COLLAPSED_ONLY = 'hidden @max-[259px]:flex';

/**
* A header action is a ghost `3xs` Button, the height FormFieldHeader's `min-h-6` row expects, in
* the muted tone of the field's other icon buttons. Its icons are 12px.
*/
export const FIELD_ACTION_CLASS =
'text-muted-foreground hover:bg-accent hover:text-foreground [&_svg]:size-3';
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Braces, ChevronDown } from 'lucide-react';
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import {
type RenderVariablePicker,
VariablePicker,
type VariablePickerItem,
} from '@/components/ui/variable-picker';
import { cn } from '@/lib';
import { COLLAPSED_HIDDEN, COLLAPSED_ICON_PADDING } from './collapse';
import { COLLAPSED_HIDDEN, FIELD_ACTION_CLASS } from './collapse';

// Shared, so an omitted `variables` is the same list on every render.
const NO_VARIABLES: VariablePickerItem[] = [];
Expand Down Expand Up @@ -100,21 +101,19 @@ export function InsertVariableAction({
if (variable.value) onInsert?.(variable.value, variable);
}}
>
<button
<Button
type="button"
variant="ghost"
size="3xs"
aria-label={text.ariaLabel}
title={text.ariaLabel}
disabled={inert}
className={cn(
'flex h-7 items-center gap-1 rounded-lg px-2 text-[11px] text-foreground-subtle transition hover:bg-surface-overlay hover:text-foreground disabled:pointer-events-none disabled:opacity-50',
COLLAPSED_ICON_PADDING,
compact && '!px-1.5'
)}
className={cn('gap-1', FIELD_ACTION_CLASS)}
>
<Braces size={12} />
<Braces />
<span className={collapsedTextClass}>{text.label}</span>
<ChevronDown size={9} className={collapsedTextClass} />
</button>
<ChevronDown className={cn('!size-2.5', collapsedTextClass)} />
</Button>
</VariablePicker>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Asterisk, ChevronDown } from 'lucide-react';
import type { ReactNode } from 'react';
import { useMemo } from 'react';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
Expand All @@ -14,11 +15,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
import type { VariablePickerItem } from '@/components/ui/variable-picker';
import { cn } from '@/lib';
import { AiAssistAction } from '../../field-actions/ai-assist-action';
import {
COLLAPSED_HIDDEN,
COLLAPSED_ICON_PADDING,
COLLAPSED_ONLY,
} from '../../field-actions/collapse';
import { COLLAPSED_HIDDEN, COLLAPSED_ONLY, FIELD_ACTION_CLASS } from '../../field-actions/collapse';
import { InsertVariableAction } from '../../field-actions/insert-variable-action';
import type { QuickFieldType, QuickFormFieldOption, QuickFormFieldStrings } from '../types';
import { FIELD_TYPE_META, FIELD_TYPE_ORDER } from '../types';
Expand Down Expand Up @@ -88,8 +85,7 @@ export function FieldHeader({
const typeMeta = FIELD_TYPE_META[fieldType];
const typeLabel = strings.typeLabels[fieldType] ?? typeMeta.label;
const collapsedTextClass = cn(COLLAPSED_HIDDEN, compact && '!hidden');
const collapsedPaddingClass = cn(COLLAPSED_ICON_PADDING, compact && '!px-1.5');
const compactOnlyClass = cn(COLLAPSED_ONLY, compact && '!block');
const compactOnlyClass = cn(COLLAPSED_ONLY, compact && '!flex');

const hasActions =
!!onFieldTypeChange || !!onRequiredChange || showFieldActions || headerActions != null;
Expand All @@ -113,19 +109,18 @@ export function FieldHeader({
<Tooltip>
<TooltipTrigger asChild>
<DropdownMenuTrigger asChild>
<button
<Button
type="button"
variant="ghost"
size="3xs"
aria-label={strings.fieldTypeAriaLabel}
disabled={disabled}
className={cn(
'flex h-7 items-center gap-1 rounded-lg px-2 text-[11px] text-foreground-subtle transition hover:bg-surface-overlay hover:text-foreground disabled:pointer-events-none disabled:opacity-50',
collapsedPaddingClass
)}
className={cn('gap-1', FIELD_ACTION_CLASS)}
>
<typeMeta.icon size={12} />
<typeMeta.icon />
<span className={collapsedTextClass}>{typeLabel}</span>
<ChevronDown size={9} className={collapsedTextClass} />
</button>
<ChevronDown className={cn('!size-2.5', collapsedTextClass)} />
</Button>
</DropdownMenuTrigger>
</TooltipTrigger>
<TooltipContent>{strings.fieldTypeTooltip}</TooltipContent>
Expand Down Expand Up @@ -177,16 +172,19 @@ export function FieldHeader({
<Tooltip>
<TooltipTrigger asChild>
<PopoverTrigger asChild>
<button
<Button
type="button"
variant="ghost"
size="3xs"
icon
aria-label={
required ? strings.requiredAriaLabel : strings.optionalAriaLabel
}
disabled={disabled}
className="grid size-7 place-items-center rounded-lg text-foreground-subtle transition hover:bg-surface-overlay hover:text-foreground disabled:pointer-events-none disabled:opacity-50"
className={FIELD_ACTION_CLASS}
>
<Asterisk size={12} />
</button>
<Asterisk />
</Button>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent>{strings.requiredTooltip}</TooltipContent>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Braces, Code2, MessageSquareText, Trash2, Type } from 'lucide-react';
import { useId, useState } from 'react';
import { Button } from '../button';
import {
DropdownMenu,
DropdownMenuContent,
Expand Down Expand Up @@ -74,16 +75,19 @@ type Story = StoryObj<typeof meta>;

function DeleteFieldButton({ onDelete }: { onDelete?: () => void }) {
return (
<button
<Button
type="button"
variant="ghost"
size="3xs"
icon
onClick={onDelete}
disabled={!onDelete}
aria-label="Delete field"
title="Delete field"
className="grid size-7 shrink-0 place-items-center rounded-lg text-foreground-subtle transition hover:bg-surface-overlay hover:text-foreground disabled:pointer-events-none disabled:opacity-50"
className="shrink-0 text-muted-foreground hover:bg-accent hover:text-foreground [&_svg]:size-3"
>
<Trash2 size={14} />
</button>
<Trash2 />
</Button>
);
}

Expand Down
Loading