@shipfox/react-ui 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/.turbo/turbo-check.log +2 -2
- package/.turbo/turbo-type.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/components/badge/index.d.ts +4 -4
- package/dist/components/badge/index.d.ts.map +1 -1
- package/dist/components/badge/index.js +4 -4
- package/dist/components/badge/index.js.map +1 -1
- package/dist/components/calendar/calendar.d.ts +5 -0
- package/dist/components/calendar/calendar.d.ts.map +1 -0
- package/dist/components/calendar/calendar.js +46 -0
- package/dist/components/calendar/calendar.js.map +1 -0
- package/dist/components/calendar/index.d.ts +2 -0
- package/dist/components/calendar/index.d.ts.map +1 -0
- package/dist/components/calendar/index.js +3 -0
- package/dist/components/calendar/index.js.map +1 -0
- package/dist/components/date-picker/date-picker.d.ts +19 -0
- package/dist/components/date-picker/date-picker.d.ts.map +1 -0
- package/dist/components/date-picker/date-picker.js +114 -0
- package/dist/components/date-picker/date-picker.js.map +1 -0
- package/dist/components/date-picker/date-picker.stories.js +333 -0
- package/dist/components/date-picker/date-picker.stories.js.map +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.d.ts.map +1 -0
- package/dist/components/date-picker/index.js +3 -0
- package/dist/components/date-picker/index.js.map +1 -0
- package/dist/components/date-time-range-picker/date-time-range-picker.d.ts +24 -0
- package/dist/components/date-time-range-picker/date-time-range-picker.d.ts.map +1 -0
- package/dist/components/date-time-range-picker/date-time-range-picker.js +130 -0
- package/dist/components/date-time-range-picker/date-time-range-picker.js.map +1 -0
- package/dist/components/date-time-range-picker/index.d.ts +2 -0
- package/dist/components/date-time-range-picker/index.d.ts.map +1 -0
- package/dist/components/date-time-range-picker/index.js +3 -0
- package/dist/components/date-time-range-picker/index.js.map +1 -0
- package/dist/components/dropdown-menu/index.d.ts +1 -2
- package/dist/components/dropdown-menu/index.d.ts.map +1 -1
- package/dist/components/dropdown-menu/index.js +1 -1
- package/dist/components/dropdown-menu/index.js.map +1 -1
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +6 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/inline-tips/inline-tips.stories.js +5 -0
- package/dist/components/inline-tips/inline-tips.stories.js.map +1 -1
- package/dist/components/item/item.stories.js +15 -8
- package/dist/components/item/item.stories.js.map +1 -1
- package/dist/components/modal/index.d.ts +1 -2
- package/dist/components/modal/index.d.ts.map +1 -1
- package/dist/components/modal/index.js +1 -1
- package/dist/components/modal/index.js.map +1 -1
- package/dist/components/modal/modal.d.ts +2 -1
- package/dist/components/modal/modal.d.ts.map +1 -1
- package/dist/components/modal/modal.js +5 -3
- package/dist/components/modal/modal.js.map +1 -1
- package/dist/components/modal/modal.stories.js +16 -6
- package/dist/components/modal/modal.stories.js.map +1 -1
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.d.ts.map +1 -0
- package/dist/components/popover/index.js +3 -0
- package/dist/components/popover/index.js.map +1 -0
- package/dist/components/popover/popover.d.ts +10 -0
- package/dist/components/popover/popover.d.ts.map +1 -0
- package/dist/components/popover/popover.js +47 -0
- package/dist/components/popover/popover.js.map +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.d.ts.map +1 -0
- package/dist/components/tabs/index.js +3 -0
- package/dist/components/tabs/index.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +50 -0
- package/dist/components/tabs/tabs.d.ts.map +1 -0
- package/dist/components/tabs/tabs.js +243 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/tabs/tabs.stories.js +179 -0
- package/dist/components/tabs/tabs.stories.js.map +1 -0
- package/dist/components/textarea/textarea.stories.js +8 -2
- package/dist/components/textarea/textarea.stories.js.map +1 -1
- package/dist/components/toast/index.d.ts +2 -2
- package/dist/components/toast/index.d.ts.map +1 -1
- package/dist/components/toast/index.js +2 -2
- package/dist/components/toast/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/debounce.d.ts +2 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/debounce.js +13 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/index.css +3 -0
- package/package.json +1 -1
- package/src/components/badge/index.ts +4 -4
- package/src/components/calendar/calendar.tsx +90 -0
- package/src/components/calendar/index.ts +1 -0
- package/src/components/date-picker/date-picker.stories.tsx +230 -0
- package/src/components/date-picker/date-picker.tsx +179 -0
- package/src/components/date-picker/index.ts +1 -0
- package/src/components/date-time-range-picker/date-time-range-picker.tsx +211 -0
- package/src/components/date-time-range-picker/index.ts +1 -0
- package/src/components/dropdown-menu/index.ts +1 -29
- package/src/components/index.ts +6 -0
- package/src/components/inline-tips/inline-tips.stories.tsx +5 -0
- package/src/components/item/item.stories.tsx +65 -56
- package/src/components/modal/index.ts +1 -23
- package/src/components/modal/modal.stories.tsx +18 -8
- package/src/components/modal/modal.tsx +4 -2
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover/popover.tsx +60 -0
- package/src/components/tabs/index.ts +1 -0
- package/src/components/tabs/tabs.stories.tsx +100 -0
- package/src/components/tabs/tabs.tsx +380 -0
- package/src/components/textarea/textarea.stories.tsx +8 -2
- package/src/components/toast/index.ts +2 -2
- package/src/utils/debounce.ts +15 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import {cva, type VariantProps} from 'class-variance-authority';
|
|
2
|
+
import {Calendar} from 'components/calendar';
|
|
3
|
+
import {Icon} from 'components/icon';
|
|
4
|
+
import {Popover, PopoverContent, PopoverTrigger} from 'components/popover';
|
|
5
|
+
import {format} from 'date-fns';
|
|
6
|
+
import type {ComponentProps, ReactNode} from 'react';
|
|
7
|
+
import {forwardRef, useState} from 'react';
|
|
8
|
+
import type {DateRange as DayPickerDateRange} from 'react-day-picker';
|
|
9
|
+
import {cn} from 'utils/cn';
|
|
10
|
+
|
|
11
|
+
export const dateTimeRangePickerVariants = cva(
|
|
12
|
+
'min-w-240 relative flex items-center rounded-6 shadow-button-neutral transition-[background-color,box-shadow] outline-none',
|
|
13
|
+
{
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
base: 'bg-background-field-base hover:bg-background-field-hover',
|
|
17
|
+
component: 'bg-background-field-component hover:bg-background-field-component-hover',
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
base: 'h-32',
|
|
21
|
+
small: 'h-28',
|
|
22
|
+
},
|
|
23
|
+
state: {
|
|
24
|
+
default: '',
|
|
25
|
+
error: 'shadow-border-error',
|
|
26
|
+
disabled:
|
|
27
|
+
'bg-background-neutral-disabled shadow-none pointer-events-none cursor-not-allowed',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: {
|
|
31
|
+
variant: 'base',
|
|
32
|
+
size: 'base',
|
|
33
|
+
state: 'default',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export type DateRange = {
|
|
39
|
+
start?: Date;
|
|
40
|
+
end?: Date;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type DateTimeRangePickerProps = Omit<ComponentProps<'input'>, 'size' | 'type'> &
|
|
44
|
+
VariantProps<typeof dateTimeRangePickerVariants> & {
|
|
45
|
+
dateRange?: DateRange;
|
|
46
|
+
onDateRangeSelect?: (range: DateRange | undefined) => void;
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
dateFormat?: string;
|
|
49
|
+
leftIcon?: ReactNode;
|
|
50
|
+
rightIcon?: ReactNode;
|
|
51
|
+
onClear?: () => void;
|
|
52
|
+
numberOfMonths?: number;
|
|
53
|
+
closeOnSelect?: boolean;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const DateTimeRangePicker = forwardRef<HTMLInputElement, DateTimeRangePickerProps>(
|
|
57
|
+
(
|
|
58
|
+
{
|
|
59
|
+
className,
|
|
60
|
+
variant,
|
|
61
|
+
size,
|
|
62
|
+
state,
|
|
63
|
+
dateRange,
|
|
64
|
+
onDateRangeSelect,
|
|
65
|
+
placeholder = 'DD/MM/YYYY - DD/MM/YYYY',
|
|
66
|
+
dateFormat = 'dd/MM/yyyy',
|
|
67
|
+
leftIcon,
|
|
68
|
+
rightIcon,
|
|
69
|
+
onClear,
|
|
70
|
+
disabled,
|
|
71
|
+
numberOfMonths = 2,
|
|
72
|
+
closeOnSelect = false,
|
|
73
|
+
...props
|
|
74
|
+
},
|
|
75
|
+
ref,
|
|
76
|
+
) => {
|
|
77
|
+
const [open, setOpen] = useState(false);
|
|
78
|
+
const isDisabled = disabled || state === 'disabled';
|
|
79
|
+
const hasRange = dateRange?.start && dateRange?.end;
|
|
80
|
+
const displayValue =
|
|
81
|
+
hasRange && dateRange.start && dateRange.end
|
|
82
|
+
? `${format(dateRange.start, dateFormat)} - ${format(dateRange.end, dateFormat)}`
|
|
83
|
+
: '';
|
|
84
|
+
|
|
85
|
+
// Convert our DateRange to react-day-picker's DateRange format
|
|
86
|
+
const dayPickerRange: DayPickerDateRange | undefined =
|
|
87
|
+
dateRange?.start || dateRange?.end
|
|
88
|
+
? {
|
|
89
|
+
from: dateRange?.start,
|
|
90
|
+
to: dateRange?.end,
|
|
91
|
+
}
|
|
92
|
+
: undefined;
|
|
93
|
+
|
|
94
|
+
const handleSelect = (selectedRange: DayPickerDateRange | undefined) => {
|
|
95
|
+
if (selectedRange) {
|
|
96
|
+
onDateRangeSelect?.({
|
|
97
|
+
start: selectedRange.from,
|
|
98
|
+
end: selectedRange.to,
|
|
99
|
+
});
|
|
100
|
+
// Only close if both dates are selected and closeOnSelect is true
|
|
101
|
+
if (closeOnSelect && selectedRange.from && selectedRange.to) {
|
|
102
|
+
setOpen(false);
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
onDateRangeSelect?.(undefined);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const handleClear = (e: React.MouseEvent) => {
|
|
110
|
+
e.stopPropagation();
|
|
111
|
+
onClear?.();
|
|
112
|
+
setOpen(false);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
117
|
+
<div
|
|
118
|
+
className={cn(
|
|
119
|
+
open && 'shadow-border-interactive-with-active',
|
|
120
|
+
dateTimeRangePickerVariants({variant, size, state: isDisabled ? 'disabled' : state}),
|
|
121
|
+
className,
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
{/* Calendar Icon Button */}
|
|
125
|
+
<PopoverTrigger asChild>
|
|
126
|
+
<button
|
|
127
|
+
type="button"
|
|
128
|
+
disabled={isDisabled}
|
|
129
|
+
className={cn(
|
|
130
|
+
'flex items-center justify-center shrink-0 transition-colors',
|
|
131
|
+
size === 'small' ? 'size-28' : 'size-32',
|
|
132
|
+
isDisabled && 'text-foreground-neutral-disabled',
|
|
133
|
+
)}
|
|
134
|
+
aria-label="Open calendar"
|
|
135
|
+
>
|
|
136
|
+
{leftIcon || (
|
|
137
|
+
<Icon
|
|
138
|
+
name="calendar2Line"
|
|
139
|
+
className={cn(
|
|
140
|
+
'size-16 text-foreground-neutral-muted',
|
|
141
|
+
isDisabled && 'text-foreground-neutral-disabled',
|
|
142
|
+
)}
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
145
|
+
</button>
|
|
146
|
+
</PopoverTrigger>
|
|
147
|
+
|
|
148
|
+
{/* Divider */}
|
|
149
|
+
<div className="h-full w-px bg-border-neutral-base shrink-0" />
|
|
150
|
+
|
|
151
|
+
{/* Input Field */}
|
|
152
|
+
<input
|
|
153
|
+
ref={ref}
|
|
154
|
+
type="text"
|
|
155
|
+
disabled={isDisabled}
|
|
156
|
+
placeholder={placeholder}
|
|
157
|
+
value={displayValue}
|
|
158
|
+
readOnly
|
|
159
|
+
className={cn(
|
|
160
|
+
'flex-1 min-w-0 px-8 text-sm leading-20 bg-transparent outline-none border-none cursor-pointer',
|
|
161
|
+
'placeholder:text-foreground-neutral-muted',
|
|
162
|
+
'text-foreground-neutral-base',
|
|
163
|
+
'disabled:text-foreground-neutral-disabled disabled:cursor-not-allowed',
|
|
164
|
+
size === 'small' ? 'py-4' : 'py-6',
|
|
165
|
+
)}
|
|
166
|
+
onClick={() => !isDisabled && setOpen(true)}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
|
|
170
|
+
{/* Clear Button (shown when date range is selected) */}
|
|
171
|
+
<button
|
|
172
|
+
type="button"
|
|
173
|
+
onClick={handleClear}
|
|
174
|
+
className={cn(
|
|
175
|
+
'flex items-center justify-center shrink-0 transition-colors hover:text-foreground-neutral-base',
|
|
176
|
+
size === 'small' ? 'size-28' : 'size-32',
|
|
177
|
+
hasRange && onClear && !isDisabled ? 'visible' : 'invisible',
|
|
178
|
+
)}
|
|
179
|
+
aria-label="Clear date range"
|
|
180
|
+
>
|
|
181
|
+
<Icon name="closeLine" className="size-16 text-foreground-neutral-muted" />
|
|
182
|
+
</button>
|
|
183
|
+
|
|
184
|
+
{/* Custom Right Icon */}
|
|
185
|
+
{rightIcon && !hasRange && (
|
|
186
|
+
<div
|
|
187
|
+
className={cn(
|
|
188
|
+
'flex items-center justify-center shrink-0',
|
|
189
|
+
size === 'small' ? 'size-28' : 'size-32',
|
|
190
|
+
)}
|
|
191
|
+
>
|
|
192
|
+
{rightIcon}
|
|
193
|
+
</div>
|
|
194
|
+
)}
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<PopoverContent className="w-auto p-0" align="start">
|
|
198
|
+
<Calendar
|
|
199
|
+
mode="range"
|
|
200
|
+
defaultMonth={dayPickerRange?.from}
|
|
201
|
+
selected={dayPickerRange}
|
|
202
|
+
onSelect={handleSelect}
|
|
203
|
+
numberOfMonths={numberOfMonths}
|
|
204
|
+
/>
|
|
205
|
+
</PopoverContent>
|
|
206
|
+
</Popover>
|
|
207
|
+
);
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
DateTimeRangePicker.displayName = 'DateTimeRangePicker';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './date-time-range-picker';
|
|
@@ -1,29 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
DropdownMenuCheckboxItemProps,
|
|
3
|
-
DropdownMenuContentProps,
|
|
4
|
-
DropdownMenuItemProps,
|
|
5
|
-
DropdownMenuLabelProps,
|
|
6
|
-
DropdownMenuRadioItemProps,
|
|
7
|
-
DropdownMenuShortcutProps,
|
|
8
|
-
DropdownMenuSubTriggerProps,
|
|
9
|
-
} from './dropdown-menu';
|
|
10
|
-
export {
|
|
11
|
-
DropdownMenu,
|
|
12
|
-
DropdownMenuCheckboxItem,
|
|
13
|
-
DropdownMenuContent,
|
|
14
|
-
DropdownMenuGroup,
|
|
15
|
-
DropdownMenuItem,
|
|
16
|
-
DropdownMenuLabel,
|
|
17
|
-
DropdownMenuPortal,
|
|
18
|
-
DropdownMenuRadioGroup,
|
|
19
|
-
DropdownMenuRadioItem,
|
|
20
|
-
DropdownMenuSeparator,
|
|
21
|
-
DropdownMenuShortcut,
|
|
22
|
-
DropdownMenuSub,
|
|
23
|
-
DropdownMenuSubContent,
|
|
24
|
-
DropdownMenuSubTrigger,
|
|
25
|
-
DropdownMenuTrigger,
|
|
26
|
-
dropdownMenuContentVariants,
|
|
27
|
-
dropdownMenuItemVariants,
|
|
28
|
-
dropdownMenuLabelVariants,
|
|
29
|
-
} from './dropdown-menu';
|
|
1
|
+
export * from './dropdown-menu';
|
package/src/components/index.ts
CHANGED
|
@@ -2,8 +2,11 @@ export * from './alert';
|
|
|
2
2
|
export * from './avatar';
|
|
3
3
|
export * from './badge';
|
|
4
4
|
export * from './button';
|
|
5
|
+
export * from './calendar';
|
|
5
6
|
export * from './checkbox';
|
|
6
7
|
export * from './code-block';
|
|
8
|
+
export * from './date-picker';
|
|
9
|
+
export * from './date-time-range-picker';
|
|
7
10
|
export * from './dot-grid';
|
|
8
11
|
export * from './dropdown-menu';
|
|
9
12
|
export * from './dynamic-item';
|
|
@@ -14,6 +17,9 @@ export * from './input';
|
|
|
14
17
|
export * from './item';
|
|
15
18
|
export * from './label';
|
|
16
19
|
export * from './modal';
|
|
20
|
+
export * from './moving-border';
|
|
21
|
+
export * from './popover';
|
|
22
|
+
export * from './tabs';
|
|
17
23
|
export * from './textarea';
|
|
18
24
|
export * from './theme';
|
|
19
25
|
export * from './toast';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {argosScreenshot} from '@argos-ci/storybook/vitest';
|
|
1
2
|
import type {Meta, StoryObj} from '@storybook/react';
|
|
2
3
|
import {Code, Header} from 'components/typography';
|
|
3
4
|
import {
|
|
@@ -37,6 +38,10 @@ const types = ['default', 'info', 'success', 'error'] as const;
|
|
|
37
38
|
const variants = ['primary', 'secondary'] as const;
|
|
38
39
|
|
|
39
40
|
export const Default: Story = {
|
|
41
|
+
play: async (ctx) => {
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
43
|
+
await argosScreenshot(ctx, 'InlineTips Default');
|
|
44
|
+
},
|
|
40
45
|
render: (args) => {
|
|
41
46
|
return (
|
|
42
47
|
<InlineTips {...args}>
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type {Meta, StoryObj} from '@storybook/react';
|
|
2
2
|
import {Button} from 'components/button/button';
|
|
3
|
+
import {DatePicker} from 'components/date-picker';
|
|
3
4
|
import {Icon} from 'components/icon/icon';
|
|
4
5
|
import {Input} from 'components/input/input';
|
|
5
6
|
import {Label} from 'components/label/label';
|
|
7
|
+
import {useState} from 'react';
|
|
6
8
|
import {
|
|
7
9
|
Item,
|
|
8
10
|
ItemActions,
|
|
@@ -38,6 +40,8 @@ const meta = {
|
|
|
38
40
|
export default meta;
|
|
39
41
|
type Story = StoryObj<typeof meta>;
|
|
40
42
|
|
|
43
|
+
const DEFAULT_START_DATE = new Date('2024-01-01T00:00:00.000Z');
|
|
44
|
+
|
|
41
45
|
export const Default: Story = {
|
|
42
46
|
args: {
|
|
43
47
|
variant: 'default',
|
|
@@ -89,62 +93,67 @@ export const Variants: Story = {
|
|
|
89
93
|
|
|
90
94
|
export const ImportPastJobsModal: Story = {
|
|
91
95
|
args: {},
|
|
92
|
-
render: () =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<ItemContent className="px-24 py-16">
|
|
114
|
-
<ItemDescription className="mb-16 text-sm text-foreground-neutral-subtle">
|
|
115
|
-
Backfill your CI history by importing past runs from your Github repo. We'll handle the
|
|
116
|
-
rest by creating a background task to import the data for you.
|
|
117
|
-
</ItemDescription>
|
|
118
|
-
<div className="flex flex-col gap-20">
|
|
119
|
-
<div className="flex flex-col gap-8">
|
|
120
|
-
<Label htmlFor="repo-owner">Repository owner</Label>
|
|
121
|
-
<Input id="repo-owner" type="text" defaultValue="apache" />
|
|
122
|
-
</div>
|
|
123
|
-
<div className="flex flex-col gap-8">
|
|
124
|
-
<Label htmlFor="repo-name">Repository name</Label>
|
|
125
|
-
<Input id="repo-name" type="text" defaultValue="kafka" />
|
|
96
|
+
render: () => {
|
|
97
|
+
const [date, setDate] = useState<Date | undefined>(DEFAULT_START_DATE);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className="flex w-full max-w-lg flex-col">
|
|
101
|
+
<Item variant="neutral">
|
|
102
|
+
<ItemHeader className="justify-between px-24 py-16">
|
|
103
|
+
<ItemTitle className="text-lg font-medium text-foreground-neutral-base">
|
|
104
|
+
Import past jobs from GitHub
|
|
105
|
+
</ItemTitle>
|
|
106
|
+
<div className="flex items-center gap-8">
|
|
107
|
+
<kbd className="flex items-center justify-center rounded-8 border border-border-neutral-base shadow-button-neutral bg-background-field-base text-xs text-foreground-neutral-subtle px-4">
|
|
108
|
+
esc
|
|
109
|
+
</kbd>
|
|
110
|
+
<Button
|
|
111
|
+
variant="transparent"
|
|
112
|
+
size="xs"
|
|
113
|
+
className="rounded-4 p-2 cursor-pointer bg-transparent border-none text-foreground-neutral-muted hover:text-foreground-neutral-base hover:bg-background-components-hover transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-background-accent-blue-base focus-visible:ring-offset-2 w-24 h-24"
|
|
114
|
+
>
|
|
115
|
+
<Icon name="close" />
|
|
116
|
+
</Button>
|
|
126
117
|
</div>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
118
|
+
</ItemHeader>
|
|
119
|
+
<ItemSeparator />
|
|
120
|
+
<ItemContent className="px-24 py-16">
|
|
121
|
+
<ItemDescription className="mb-16 text-sm text-foreground-neutral-subtle">
|
|
122
|
+
Backfill your CI history by importing past runs from your GitHub repo. We'll handle
|
|
123
|
+
the rest by creating a background task to import the data for you.
|
|
124
|
+
</ItemDescription>
|
|
125
|
+
<div className="flex flex-col gap-20">
|
|
126
|
+
<div className="flex flex-col gap-8">
|
|
127
|
+
<Label htmlFor="repo-owner">Repository owner</Label>
|
|
128
|
+
<Input id="repo-owner" type="text" defaultValue="apache" />
|
|
129
|
+
</div>
|
|
130
|
+
<div className="flex flex-col gap-8">
|
|
131
|
+
<Label htmlFor="repo-name">Repository name</Label>
|
|
132
|
+
<Input id="repo-name" type="text" defaultValue="kafka" />
|
|
133
|
+
</div>
|
|
134
|
+
<div className="flex flex-col gap-8">
|
|
135
|
+
<Label htmlFor="start-date">Start date</Label>
|
|
136
|
+
<DatePicker
|
|
137
|
+
id="start-date"
|
|
138
|
+
date={date}
|
|
139
|
+
onDateSelect={setDate}
|
|
140
|
+
onClear={() => setDate(undefined)}
|
|
141
|
+
placeholder="DD/MM/YYYY"
|
|
142
|
+
/>
|
|
143
|
+
</div>
|
|
135
144
|
</div>
|
|
136
|
-
</
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
</
|
|
146
|
-
</
|
|
147
|
-
</
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
</ItemContent>
|
|
146
|
+
<ItemSeparator />
|
|
147
|
+
<ItemFooter className="justify-end gap-8 px-24 py-16">
|
|
148
|
+
<Button variant="transparent" size="sm">
|
|
149
|
+
Cancel
|
|
150
|
+
</Button>
|
|
151
|
+
<Button variant="primary" size="sm">
|
|
152
|
+
Import
|
|
153
|
+
</Button>
|
|
154
|
+
</ItemFooter>
|
|
155
|
+
</Item>
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
},
|
|
150
159
|
};
|
|
@@ -1,23 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
ModalContentProps,
|
|
3
|
-
ModalDescriptionProps,
|
|
4
|
-
ModalHeaderProps,
|
|
5
|
-
ModalOverlayProps,
|
|
6
|
-
ModalTitleProps,
|
|
7
|
-
} from './modal';
|
|
8
|
-
export {
|
|
9
|
-
Modal,
|
|
10
|
-
ModalBody,
|
|
11
|
-
ModalClose,
|
|
12
|
-
ModalContent,
|
|
13
|
-
ModalDescription,
|
|
14
|
-
ModalFooter,
|
|
15
|
-
ModalHeader,
|
|
16
|
-
ModalOverlay,
|
|
17
|
-
ModalPortal,
|
|
18
|
-
ModalTitle,
|
|
19
|
-
ModalTrigger,
|
|
20
|
-
modalContentVariants,
|
|
21
|
-
modalDefaultTransition,
|
|
22
|
-
modalOverlayVariants,
|
|
23
|
-
} from './modal';
|
|
1
|
+
export * from './modal';
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
CodeBlockHeader,
|
|
15
15
|
CodeBlockItem,
|
|
16
16
|
} from 'components/code-block';
|
|
17
|
+
import {DatePicker} from 'components/date-picker';
|
|
17
18
|
import {DynamicItem} from 'components/dynamic-item';
|
|
18
19
|
import {Icon} from 'components/icon';
|
|
19
20
|
import {Input} from 'components/input';
|
|
@@ -39,6 +40,8 @@ const OPEN_MODAL_REGEX = /open modal/i;
|
|
|
39
40
|
const IMPORT_JOBS_REGEX = /import past jobs from github/i;
|
|
40
41
|
const GITHUB_ACTIONS_REGEX = /run github actions on shipfox/i;
|
|
41
42
|
|
|
43
|
+
const DEFAULT_START_DATE = new Date('2025-12-06T00:00:00.000Z');
|
|
44
|
+
|
|
42
45
|
const meta = {
|
|
43
46
|
title: 'Components/Modal',
|
|
44
47
|
component: Modal,
|
|
@@ -129,19 +132,20 @@ export const ImportForm: Story = {
|
|
|
129
132
|
},
|
|
130
133
|
render: () => {
|
|
131
134
|
const [open, setOpen] = useState(false);
|
|
135
|
+
const [date, setDate] = useState<Date | undefined>(DEFAULT_START_DATE);
|
|
132
136
|
|
|
133
137
|
return (
|
|
134
138
|
<div className="flex h-[calc(100vh/2)] w-[calc(100vw/2)] items-center justify-center rounded-16 bg-background-subtle-base shadow-tooltip">
|
|
135
139
|
<Modal open={open} onOpenChange={setOpen}>
|
|
136
140
|
<ModalTrigger asChild>
|
|
137
|
-
<Button>Import past jobs from
|
|
141
|
+
<Button>Import past jobs from GitHub</Button>
|
|
138
142
|
</ModalTrigger>
|
|
139
|
-
<ModalContent aria-describedby={undefined}>
|
|
140
|
-
<ModalTitle className="sr-only">Import past jobs from
|
|
141
|
-
<ModalHeader title="Import past jobs from
|
|
143
|
+
<ModalContent aria-describedby={undefined} overlayClassName="bg-background-modal-overlay">
|
|
144
|
+
<ModalTitle className="sr-only">Import past jobs from GitHub</ModalTitle>
|
|
145
|
+
<ModalHeader title="Import past jobs from GitHub" />
|
|
142
146
|
<ModalBody className="gap-20">
|
|
143
147
|
<Text size="sm" className="text-foreground-neutral-subtle w-full">
|
|
144
|
-
Backfill your CI history by importing past runs from your
|
|
148
|
+
Backfill your CI history by importing past runs from your GitHub repo. We'll
|
|
145
149
|
handle the rest by creating a background task to import the data for you.
|
|
146
150
|
</Text>
|
|
147
151
|
<div className="flex flex-col gap-20 w-full">
|
|
@@ -154,8 +158,14 @@ export const ImportForm: Story = {
|
|
|
154
158
|
<Input placeholder="kafka" />
|
|
155
159
|
</div>
|
|
156
160
|
<div className="flex flex-col gap-8 w-full">
|
|
157
|
-
<Label>Start date</Label>
|
|
158
|
-
<
|
|
161
|
+
<Label htmlFor="start-date">Start date</Label>
|
|
162
|
+
<DatePicker
|
|
163
|
+
id="start-date"
|
|
164
|
+
date={date}
|
|
165
|
+
onDateSelect={setDate}
|
|
166
|
+
onClear={() => setDate(undefined)}
|
|
167
|
+
placeholder="DD/MM/YYYY"
|
|
168
|
+
/>
|
|
159
169
|
</div>
|
|
160
170
|
</div>
|
|
161
171
|
</ModalBody>
|
|
@@ -211,7 +221,7 @@ export const GithubActions: Story = {
|
|
|
211
221
|
<ModalTrigger asChild>
|
|
212
222
|
<Button>Run GitHub Actions on Shipfox</Button>
|
|
213
223
|
</ModalTrigger>
|
|
214
|
-
<ModalContent aria-describedby={undefined}>
|
|
224
|
+
<ModalContent aria-describedby={undefined} overlayClassName="bg-background-modal-overlay">
|
|
215
225
|
<ModalTitle className="sr-only">Run GitHub Actions on Shipfox</ModalTitle>
|
|
216
226
|
<ModalHeader title="Run GitHub Actions on Shipfox" />
|
|
217
227
|
<ModalBody className="gap-32">
|
|
@@ -125,6 +125,7 @@ function ModalOverlay({
|
|
|
125
125
|
type ModalContentProps = ComponentProps<typeof DialogPrimitive.Content> & {
|
|
126
126
|
animated?: boolean;
|
|
127
127
|
transition?: Transition;
|
|
128
|
+
overlayClassName?: string;
|
|
128
129
|
};
|
|
129
130
|
|
|
130
131
|
function ModalContent({
|
|
@@ -132,6 +133,7 @@ function ModalContent({
|
|
|
132
133
|
children,
|
|
133
134
|
animated = true,
|
|
134
135
|
transition = modalDefaultTransition,
|
|
136
|
+
overlayClassName,
|
|
135
137
|
...props
|
|
136
138
|
}: ModalContentProps) {
|
|
137
139
|
const {isDesktop} = useModalContext();
|
|
@@ -139,7 +141,7 @@ function ModalContent({
|
|
|
139
141
|
if (!isDesktop) {
|
|
140
142
|
return (
|
|
141
143
|
<ModalPortal>
|
|
142
|
-
<ModalOverlay animated={animated} transition={transition} />
|
|
144
|
+
<ModalOverlay animated={animated} transition={transition} className={overlayClassName} />
|
|
143
145
|
<VaulDrawer.Content
|
|
144
146
|
className={cn(
|
|
145
147
|
'fixed bottom-0 left-0 right-0 z-50 flex flex-col bg-background-neutral-base rounded-t-16 max-h-[85vh] shadow-tooltip',
|
|
@@ -163,7 +165,7 @@ function ModalContent({
|
|
|
163
165
|
|
|
164
166
|
return (
|
|
165
167
|
<ModalPortal>
|
|
166
|
-
<ModalOverlay animated={animated} transition={transition} />
|
|
168
|
+
<ModalOverlay animated={animated} transition={transition} className={overlayClassName} />
|
|
167
169
|
<DialogPrimitive.Content className={baseClasses} {...props}>
|
|
168
170
|
<div className="relative size-full">
|
|
169
171
|
<div className="pointer-events-none absolute inset-0 shadow-separator-inset rounded-16" />
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './popover';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
2
|
+
import type {ComponentProps} from 'react';
|
|
3
|
+
import {cn} from 'utils/cn';
|
|
4
|
+
|
|
5
|
+
function Popover({...props}: ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
6
|
+
return <PopoverPrimitive.Root {...props} />;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function PopoverTrigger({...props}: ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
10
|
+
return <PopoverPrimitive.Trigger {...props} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function PopoverAnchor({...props}: ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
14
|
+
return <PopoverPrimitive.Anchor {...props} />;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function PopoverPortal({...props}: ComponentProps<typeof PopoverPrimitive.Portal>) {
|
|
18
|
+
return <PopoverPrimitive.Portal {...props} />;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function PopoverContent({
|
|
22
|
+
className,
|
|
23
|
+
align = 'center',
|
|
24
|
+
sideOffset = 4,
|
|
25
|
+
...props
|
|
26
|
+
}: ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
27
|
+
return (
|
|
28
|
+
<PopoverPortal>
|
|
29
|
+
<PopoverPrimitive.Content
|
|
30
|
+
align={align}
|
|
31
|
+
sideOffset={sideOffset}
|
|
32
|
+
className={cn(
|
|
33
|
+
'z-50 rounded-10 bg-background-neutral-overlay shadow-tooltip outline-none',
|
|
34
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
|
35
|
+
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
36
|
+
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
37
|
+
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',
|
|
38
|
+
'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
39
|
+
className,
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
</PopoverPortal>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function PopoverArrow({className, ...props}: ComponentProps<typeof PopoverPrimitive.Arrow>) {
|
|
48
|
+
return (
|
|
49
|
+
<PopoverPrimitive.Arrow
|
|
50
|
+
className={cn('fill-background-neutral-overlay', className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function PopoverClose({...props}: ComponentProps<typeof PopoverPrimitive.Close>) {
|
|
57
|
+
return <PopoverPrimitive.Close {...props} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {Popover, PopoverTrigger, PopoverAnchor, PopoverContent, PopoverArrow, PopoverClose};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './tabs';
|