Skip to content

Commit 17ab8a8

Browse files
committed
fix(subscription): improve layout and drag-and-drop functionality in subscription rules section
- Adjust styles for better overflow handling and responsiveness in sortable subscription rules - Implement custom drag-and-drop modifiers to enhance user experience - Refine spacing and structure in advanced sheet component for consistency
1 parent bb91ad0 commit 17ab8a8

4 files changed

Lines changed: 31 additions & 8 deletions

File tree

dashboard/src/components/subscriptions/sortable-subscription-rule.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ export function SortableSubscriptionRule({ index, onRemove, form, id }: Sortable
115115

116116
return (
117117
<>
118-
<div ref={setNodeRef} style={style} className="cursor-default" dir="ltr">
119-
<div className="group relative flex flex-col gap-2 rounded-md border bg-card p-2 transition-colors hover:bg-accent/20 sm:flex-row sm:items-center sm:gap-3 sm:p-3">
118+
<div ref={setNodeRef} style={style} className="min-w-0 max-w-full cursor-default overflow-hidden" dir="ltr">
119+
<div className="group relative flex min-w-0 max-w-full flex-col gap-2 overflow-hidden rounded-md border bg-card p-2 transition-colors hover:bg-accent/20 sm:flex-row sm:items-center sm:gap-3 sm:p-3">
120120
<div className="flex min-w-0 flex-1 flex-row gap-1 sm:gap-1.5">
121121
<button
122122
type="button"

dashboard/src/components/subscriptions/subscription-rule-advanced-sheet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export function SubscriptionRuleAdvancedSheet({
116116
</Button>
117117
</div>
118118

119-
<div className="max-h-[min(50dvh,24rem)] space-y-3 overflow-y-auto pr-0.5">
119+
<div className="max-h-[min(50dvh,24rem)] space-y-3 overflow-y-auto p-px">
120120
{responseHeaderCount > 0 ? (
121121
responseHeaderEntries.map(([headerKey, headerValue], index) => (
122122
<div key={`${rowId}-header-${index}`} className="space-y-2 rounded-lg border bg-card/50 p-3">

dashboard/src/components/subscriptions/subscription-rules-section.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ import type { SubscriptionFormData } from '@/components/subscriptions/subscripti
33
import { Badge } from '@/components/ui/badge'
44
import { Button } from '@/components/ui/button'
55
import { closestCenter, DndContext, DragEndEvent } from '@dnd-kit/core'
6+
import type { Modifier } from '@dnd-kit/core'
67
import { rectSortingStrategy, SortableContext } from '@dnd-kit/sortable'
78
import { FileText, Plus, RotateCcw } from 'lucide-react'
89
import type { ComponentProps } from 'react'
10+
import { useMemo, useRef } from 'react'
911
import type { FieldArrayWithId } from 'react-hook-form'
1012
import { UseFormReturn } from 'react-hook-form'
1113
import { useTranslation } from 'react-i18next'
1214

1315
type DndContextSensors = NonNullable<ComponentProps<typeof DndContext>['sensors']>
1416

17+
const clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max)
18+
1519
export interface SubscriptionRulesSectionProps {
1620
form: UseFormReturn<SubscriptionFormData>
1721
ruleFields: FieldArrayWithId<SubscriptionFormData, 'rules'>[]
@@ -34,9 +38,28 @@ export function SubscriptionRulesSection({
3438
isSaving,
3539
}: SubscriptionRulesSectionProps) {
3640
const { t } = useTranslation()
41+
const rulesListRef = useRef<HTMLDivElement>(null)
42+
const rulesModifiers = useMemo<Modifier[]>(
43+
() => [
44+
({ transform, draggingNodeRect }) => {
45+
const listRect = rulesListRef.current?.getBoundingClientRect()
46+
if (!draggingNodeRect || !listRect) {
47+
return { ...transform, x: 0 }
48+
}
49+
const edgeAllowance = clamp(draggingNodeRect.height, 56, 120)
50+
51+
return {
52+
...transform,
53+
x: 0,
54+
y: clamp(transform.y, listRect.top - draggingNodeRect.top - edgeAllowance, listRect.bottom - draggingNodeRect.bottom + edgeAllowance),
55+
}
56+
},
57+
],
58+
[],
59+
)
3760

3861
return (
39-
<div className="space-y-3">
62+
<div className="min-w-0 space-y-3 overflow-hidden">
4063
<div className="rounded-lg border bg-card p-3 shadow-sm sm:p-4">
4164
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4">
4265
<div className="min-w-0 flex-1 space-y-1">
@@ -70,10 +93,10 @@ export function SubscriptionRulesSection({
7093
<p className="mb-1 text-xs font-medium sm:text-sm">{t('settings.subscriptions.rules.noRules')}</p>
7194
</div>
7295
) : (
73-
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={onDragEnd}>
74-
<div dir="ltr">
96+
<DndContext sensors={sensors} collisionDetection={closestCenter} modifiers={rulesModifiers} onDragEnd={onDragEnd}>
97+
<div dir="ltr" className="min-w-0 overflow-hidden">
7598
<SortableContext items={ruleFields.map(field => field.id)} strategy={rectSortingStrategy}>
76-
<div className="scrollbar-thin flex max-h-[min(70vh,500px)] touch-pan-y flex-col gap-2 overflow-y-auto py-1 sm:max-h-[500px] sm:gap-2.5 sm:py-1">
99+
<div ref={rulesListRef} className="scrollbar-thin flex max-h-[min(70vh,500px)] min-w-0 touch-pan-y flex-col gap-2 overflow-y-auto overflow-x-hidden py-1 sm:max-h-[500px] sm:gap-2.5 sm:py-1">
77100
{ruleFields.map((field, index) => (
78101
<SortableSubscriptionRule key={field.id} id={field.id} index={index} onRemove={onRemoveRule} form={form} />
79102
))}

dashboard/src/components/ui/sheet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const SheetOverlay = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Ove
2323
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
2424

2525
const sheetVariants = cva(
26-
'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out',
26+
'fixed z-50 gap-4 bg-background p-6 shadow-lg outline-none transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out',
2727
{
2828
variants: {
2929
side: {

0 commit comments

Comments
 (0)