paris 0.21.2 → 0.22.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/CHANGELOG.md +39 -0
- package/package.json +1 -1
- package/src/helpers/OpenChangeEffect.tsx +21 -0
- package/src/helpers/useControllableState.test.ts +88 -0
- package/src/helpers/useControllableState.ts +59 -0
- package/src/stories/accordionselect/AccordionSelect.test.tsx +72 -0
- package/src/stories/accordionselect/AccordionSelect.tsx +22 -12
- package/src/stories/checkbox/Checkbox.test.tsx +53 -0
- package/src/stories/checkbox/Checkbox.tsx +21 -6
- package/src/stories/combobox/Combobox.test.tsx +111 -0
- package/src/stories/combobox/Combobox.tsx +192 -137
- package/src/stories/drawer/Drawer.module.scss +56 -15
- package/src/stories/drawer/Drawer.stories.tsx +287 -109
- package/src/stories/drawer/Drawer.test.tsx +486 -11
- package/src/stories/drawer/Drawer.tsx +366 -240
- package/src/stories/drawer/DrawerActions.tsx +28 -0
- package/src/stories/drawer/DrawerBottomPanel.tsx +55 -0
- package/src/stories/drawer/DrawerContext.tsx +31 -0
- package/src/stories/drawer/DrawerPage.tsx +37 -0
- package/src/stories/drawer/DrawerPageContext.tsx +35 -0
- package/src/stories/drawer/DrawerPaginationContext.tsx +22 -0
- package/src/stories/drawer/DrawerProgressBar.tsx +72 -0
- package/src/stories/drawer/DrawerSlotContext.tsx +172 -0
- package/src/stories/drawer/DrawerTitle.tsx +35 -0
- package/src/stories/drawer/index.ts +9 -0
- package/src/stories/menu/Menu.test.tsx +43 -0
- package/src/stories/menu/Menu.tsx +13 -2
- package/src/stories/popover/Popover.tsx +8 -5
- package/src/stories/select/Select.module.scss +1 -1
- package/src/stories/select/Select.test.tsx +108 -0
- package/src/stories/select/Select.tsx +121 -92
- package/src/test/render.tsx +2 -2
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
import { faClose } from '@fortawesome/free-solid-svg-icons';
|
|
4
4
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ComboboxButton,
|
|
7
|
+
ComboboxInput,
|
|
8
|
+
ComboboxOption,
|
|
9
|
+
ComboboxOptions,
|
|
10
|
+
Combobox as HCombobox,
|
|
11
|
+
} from '@headlessui/react';
|
|
6
12
|
import { clsx } from 'clsx';
|
|
7
|
-
import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react';
|
|
8
|
-
import { useId, useMemo, useState } from 'react';
|
|
13
|
+
import type { ComponentPropsWithoutRef, CSSProperties, MouseEvent, ReactNode } from 'react';
|
|
14
|
+
import { useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
15
|
+
import { OpenChangeEffect } from '../../helpers/OpenChangeEffect';
|
|
9
16
|
import { MemoizedEnhancer } from '../../helpers/renderEnhancer';
|
|
17
|
+
import { useControllableState } from '../../helpers/useControllableState';
|
|
10
18
|
import type { ButtonProps } from '../button';
|
|
11
19
|
import { Button } from '../button';
|
|
12
20
|
import type { FieldProps } from '../field';
|
|
@@ -46,6 +54,10 @@ export type ComboboxProps<T extends Record<string, any>> = {
|
|
|
46
54
|
* If `null`, no option will be selected.
|
|
47
55
|
*/
|
|
48
56
|
value?: Option<T> | null;
|
|
57
|
+
/**
|
|
58
|
+
* The initial value for uncontrolled mode. If `value` is provided, this is ignored.
|
|
59
|
+
*/
|
|
60
|
+
defaultValue?: Option<T> | null;
|
|
49
61
|
/**
|
|
50
62
|
* The interaction handler for the Combobox. This will be called when the user selects an option from the dropdown.
|
|
51
63
|
*
|
|
@@ -81,6 +93,10 @@ export type ComboboxProps<T extends Record<string, any>> = {
|
|
|
81
93
|
* @param value
|
|
82
94
|
*/
|
|
83
95
|
customValueToOption?: (value: string) => Option<T>;
|
|
96
|
+
/**
|
|
97
|
+
* Called when the combobox dropdown opens or closes.
|
|
98
|
+
*/
|
|
99
|
+
onOpenChange?: (open: boolean) => void;
|
|
84
100
|
/**
|
|
85
101
|
* Whether to hide the clear button when a value is selected. This will never be hidden if the selected option's node is not a strong, because there is no other way to clear the value as of now.
|
|
86
102
|
*/
|
|
@@ -137,6 +153,7 @@ export type ComboboxProps<T extends Record<string, any>> = {
|
|
|
137
153
|
export function Combobox<T extends Record<string, any> = Record<string, any>>({
|
|
138
154
|
options,
|
|
139
155
|
value,
|
|
156
|
+
defaultValue,
|
|
140
157
|
onChange,
|
|
141
158
|
label,
|
|
142
159
|
status,
|
|
@@ -153,6 +170,7 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
|
|
|
153
170
|
showCustomValueOption = true,
|
|
154
171
|
customValueString = 'Create "%v"',
|
|
155
172
|
customValueToOption,
|
|
173
|
+
onOpenChange,
|
|
156
174
|
hideClearButton = false,
|
|
157
175
|
maxHeight = 320,
|
|
158
176
|
hasOptionBorder = false,
|
|
@@ -160,8 +178,31 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
|
|
|
160
178
|
overrides,
|
|
161
179
|
}: ComboboxProps<T>) {
|
|
162
180
|
const inputID = useId();
|
|
163
|
-
const [
|
|
181
|
+
const [resolvedValue, setResolvedValue] = useControllableState<Option<T> | null>({
|
|
182
|
+
value,
|
|
183
|
+
defaultValue,
|
|
184
|
+
onChange,
|
|
185
|
+
});
|
|
164
186
|
const [query, setQuery] = useState('');
|
|
187
|
+
const containerElRef = useRef<HTMLElement | null>(null);
|
|
188
|
+
const inputElRef = useRef<HTMLElement | null>(null);
|
|
189
|
+
const [anchorOffset, setAnchorOffset] = useState(0);
|
|
190
|
+
|
|
191
|
+
const containerRef = useCallback((node: HTMLButtonElement | null) => {
|
|
192
|
+
containerElRef.current = node;
|
|
193
|
+
}, []);
|
|
194
|
+
|
|
195
|
+
const inputRef = useCallback((node: HTMLInputElement | null) => {
|
|
196
|
+
inputElRef.current = node;
|
|
197
|
+
}, []);
|
|
198
|
+
|
|
199
|
+
useLayoutEffect(() => {
|
|
200
|
+
if (containerElRef.current && inputElRef.current) {
|
|
201
|
+
const containerLeft = containerElRef.current.getBoundingClientRect().left;
|
|
202
|
+
const inputLeft = inputElRef.current.getBoundingClientRect().left;
|
|
203
|
+
setAnchorOffset(containerLeft - inputLeft);
|
|
204
|
+
}
|
|
205
|
+
}, [startEnhancer, resolvedValue]);
|
|
165
206
|
|
|
166
207
|
const optionsWithCustomValue = useMemo(
|
|
167
208
|
() => [...(allowCustomValue && customValueToOption ? [customValueToOption(query)] : []), ...options],
|
|
@@ -187,154 +228,168 @@ export function Combobox<T extends Record<string, any> = Record<string, any>>({
|
|
|
187
228
|
<HCombobox
|
|
188
229
|
as="div"
|
|
189
230
|
immediate={!hideOptionsInitially}
|
|
190
|
-
value={
|
|
231
|
+
value={resolvedValue?.id ?? null}
|
|
191
232
|
onChange={(id) => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
} else if (id) {
|
|
198
|
-
onChange({
|
|
199
|
-
id: null,
|
|
200
|
-
node: id,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
233
|
+
const sel = optionsWithCustomValue.find((o) => o.id === id);
|
|
234
|
+
if (sel) {
|
|
235
|
+
setResolvedValue(sel);
|
|
236
|
+
} else if (id) {
|
|
237
|
+
setResolvedValue({ id: null, node: id } as Option<T>);
|
|
203
238
|
}
|
|
204
239
|
}}
|
|
205
240
|
>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
{...overrides?.startEnhancerContainer}
|
|
214
|
-
className={clsx(inputStyles.enhancer, overrides?.startEnhancerContainer?.className)}
|
|
241
|
+
{({ open }) => (
|
|
242
|
+
<>
|
|
243
|
+
<OpenChangeEffect open={open} onOpenChange={onOpenChange} />
|
|
244
|
+
<ComboboxButton
|
|
245
|
+
as="div"
|
|
246
|
+
ref={containerRef}
|
|
247
|
+
tabIndex={-1}
|
|
215
248
|
data-status={disabled ? 'disabled' : status || 'default'}
|
|
249
|
+
{...overrides?.inputContainer}
|
|
250
|
+
className={clsx(overrides?.inputContainer?.className, inputStyles.inputContainer)}
|
|
216
251
|
>
|
|
217
252
|
{!!startEnhancer && (
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
253
|
+
<div
|
|
254
|
+
{...overrides?.startEnhancerContainer}
|
|
255
|
+
className={clsx(inputStyles.enhancer, overrides?.startEnhancerContainer?.className)}
|
|
256
|
+
data-status={disabled ? 'disabled' : status || 'default'}
|
|
257
|
+
>
|
|
258
|
+
{!!startEnhancer && (
|
|
259
|
+
<MemoizedEnhancer
|
|
260
|
+
enhancer={startEnhancer}
|
|
261
|
+
size={parseInt(
|
|
262
|
+
pget('typography.styles.paragraphSmall.fontSize') ||
|
|
263
|
+
theme.typography.styles.paragraphSmall.fontSize,
|
|
264
|
+
10,
|
|
265
|
+
)}
|
|
266
|
+
/>
|
|
224
267
|
)}
|
|
225
|
-
|
|
268
|
+
</div>
|
|
226
269
|
)}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
270
|
+
<div className={styles.content}>
|
|
271
|
+
{resolvedValue?.node && typeof resolvedValue.node !== 'string' ? (
|
|
272
|
+
resolvedValue.node
|
|
273
|
+
) : (
|
|
274
|
+
<ComboboxInput
|
|
275
|
+
ref={inputRef}
|
|
276
|
+
id={inputID}
|
|
277
|
+
{...overrides?.input}
|
|
278
|
+
placeholder={placeholder}
|
|
279
|
+
// value={query}
|
|
280
|
+
displayValue={() => resolvedValue?.node as string}
|
|
281
|
+
onClick={(e: MouseEvent<HTMLInputElement>) => {
|
|
282
|
+
e.stopPropagation();
|
|
283
|
+
overrides?.input?.onClick?.(e);
|
|
284
|
+
}}
|
|
285
|
+
onKeyDown={(e) => {
|
|
286
|
+
e.stopPropagation();
|
|
287
|
+
overrides?.input?.onKeyDown?.(e);
|
|
288
|
+
}}
|
|
289
|
+
onChange={(e) => {
|
|
290
|
+
setQuery(e.target.value);
|
|
291
|
+
if (onInputChange) onInputChange(e.target.value);
|
|
292
|
+
if (overrides?.input?.onChange) overrides.input.onChange(e);
|
|
293
|
+
if (allowCustomValue && e.target.value) {
|
|
294
|
+
setResolvedValue(
|
|
295
|
+
customValueToOption?.(e.target.value) ||
|
|
296
|
+
({
|
|
297
|
+
id: null,
|
|
298
|
+
node: e.target.value,
|
|
299
|
+
} as Option<T>),
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}}
|
|
303
|
+
aria-disabled={disabled}
|
|
304
|
+
data-status={disabled ? 'disabled' : status || 'default'}
|
|
305
|
+
className={clsx(overrides?.input?.className, inputStyles.input, styles.field)}
|
|
306
|
+
/>
|
|
307
|
+
)}
|
|
308
|
+
</div>
|
|
258
309
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
</Button>
|
|
274
|
-
)}
|
|
275
|
-
{!!endEnhancer && (
|
|
276
|
-
<div
|
|
277
|
-
{...overrides?.endEnhancerContainer}
|
|
278
|
-
className={clsx(inputStyles.enhancer, overrides?.endEnhancerContainer?.className)}
|
|
279
|
-
data-status={disabled ? 'disabled' : status || 'default'}
|
|
280
|
-
>
|
|
310
|
+
{!!resolvedValue && (!hideClearButton || typeof resolvedValue.node !== 'string') && (
|
|
311
|
+
<Button
|
|
312
|
+
size="xs"
|
|
313
|
+
shape="circle"
|
|
314
|
+
startEnhancer={<FontAwesomeIcon icon={faClose} fontSize="10px" />}
|
|
315
|
+
onClick={(e) => {
|
|
316
|
+
e.stopPropagation();
|
|
317
|
+
setResolvedValue(null);
|
|
318
|
+
}}
|
|
319
|
+
{...overrides?.clearButton}
|
|
320
|
+
>
|
|
321
|
+
Clear
|
|
322
|
+
</Button>
|
|
323
|
+
)}
|
|
281
324
|
{!!endEnhancer && (
|
|
282
|
-
<
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
325
|
+
<div
|
|
326
|
+
{...overrides?.endEnhancerContainer}
|
|
327
|
+
className={clsx(inputStyles.enhancer, overrides?.endEnhancerContainer?.className)}
|
|
328
|
+
data-status={disabled ? 'disabled' : status || 'default'}
|
|
329
|
+
>
|
|
330
|
+
{!!endEnhancer && (
|
|
331
|
+
<MemoizedEnhancer
|
|
332
|
+
enhancer={endEnhancer}
|
|
333
|
+
size={parseInt(
|
|
334
|
+
pget('typography.styles.paragraphSmall.fontSize') ||
|
|
335
|
+
theme.typography.styles.paragraphSmall.fontSize,
|
|
336
|
+
10,
|
|
337
|
+
)}
|
|
338
|
+
/>
|
|
288
339
|
)}
|
|
289
|
-
|
|
340
|
+
</div>
|
|
290
341
|
)}
|
|
291
|
-
</
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
<ComboboxOption
|
|
309
|
-
as="li"
|
|
310
|
-
value={query}
|
|
311
|
-
data-selected={false}
|
|
312
|
-
className={clsx(overrides?.customValueOption?.className, styles.option)}
|
|
313
|
-
{...overrides?.customValueOption}
|
|
342
|
+
</ComboboxButton>
|
|
343
|
+
<ComboboxOptions
|
|
344
|
+
as="ul"
|
|
345
|
+
anchor={{
|
|
346
|
+
to: 'bottom start',
|
|
347
|
+
gap: 9,
|
|
348
|
+
offset: anchorOffset,
|
|
349
|
+
}}
|
|
350
|
+
transition
|
|
351
|
+
{...overrides?.optionsContainer}
|
|
352
|
+
className={clsx(overrides?.optionsContainer?.className, styles.options)}
|
|
353
|
+
style={
|
|
354
|
+
{
|
|
355
|
+
'--options-maxHeight': `${maxHeight}px`,
|
|
356
|
+
...overrides?.optionsContainer?.style,
|
|
357
|
+
} as CSSProperties
|
|
358
|
+
}
|
|
314
359
|
>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
overrides?.option?.className,
|
|
328
|
-
styles.option,
|
|
329
|
-
hasOptionBorder && styles.optionBorder,
|
|
360
|
+
{allowCustomValue && showCustomValueOption && !customValueToOption && query.length > 0 && (
|
|
361
|
+
<ComboboxOption
|
|
362
|
+
as="li"
|
|
363
|
+
value={query}
|
|
364
|
+
data-selected={false}
|
|
365
|
+
className={clsx(overrides?.customValueOption?.className, styles.option)}
|
|
366
|
+
{...overrides?.customValueOption}
|
|
367
|
+
>
|
|
368
|
+
<Text as="span" kind="paragraphSmall">
|
|
369
|
+
{customValueString.replace('%v', query)}
|
|
370
|
+
</Text>
|
|
371
|
+
</ComboboxOption>
|
|
330
372
|
)}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
373
|
+
{(optionsWithCustomValue || []).map((option) => (
|
|
374
|
+
<ComboboxOption
|
|
375
|
+
as="li"
|
|
376
|
+
key={option.id}
|
|
377
|
+
value={option.id}
|
|
378
|
+
{...overrides?.option}
|
|
379
|
+
className={clsx(
|
|
380
|
+
overrides?.option?.className,
|
|
381
|
+
styles.option,
|
|
382
|
+
hasOptionBorder && styles.optionBorder,
|
|
383
|
+
)}
|
|
384
|
+
>
|
|
385
|
+
<TextWhenString as="span" kind="paragraphSmall">
|
|
386
|
+
{option.node}
|
|
387
|
+
</TextWhenString>
|
|
388
|
+
</ComboboxOption>
|
|
389
|
+
))}
|
|
390
|
+
</ComboboxOptions>
|
|
391
|
+
</>
|
|
392
|
+
)}
|
|
338
393
|
</HCombobox>
|
|
339
394
|
</Field>
|
|
340
395
|
);
|
|
@@ -11,8 +11,6 @@ $panelPaddingY: 20px;
|
|
|
11
11
|
$duration: var(--pte-animations-duration-relaxed);
|
|
12
12
|
$paginationDuration: var(--pte-animations-duration-normal);
|
|
13
13
|
$panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
14
|
-
//$panelAnimationDelay: var(--pte-animations-duration-rapid);
|
|
15
|
-
//$duration: var(--pte-animations-duration-normal);
|
|
16
14
|
|
|
17
15
|
.root {
|
|
18
16
|
position: fixed;
|
|
@@ -275,7 +273,6 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
275
273
|
position: relative;
|
|
276
274
|
height: 100%;
|
|
277
275
|
padding: 0;
|
|
278
|
-
//padding: $panelPaddingY $panelPaddingX;
|
|
279
276
|
background-color: var(--pte-new-colors-surfacePrimary);
|
|
280
277
|
overflow: auto;
|
|
281
278
|
|
|
@@ -283,7 +280,6 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
283
280
|
flex-direction: column;
|
|
284
281
|
justify-content: flex-start;
|
|
285
282
|
align-items: stretch;
|
|
286
|
-
//gap: $panelPaddingY;
|
|
287
283
|
|
|
288
284
|
&.enterFrom {
|
|
289
285
|
box-shadow: none;
|
|
@@ -339,14 +335,9 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
339
335
|
|
|
340
336
|
.actionMenu {}
|
|
341
337
|
|
|
342
|
-
.closeButton {
|
|
343
|
-
//position: absolute;
|
|
344
|
-
//right: $panelPaddingX;
|
|
345
|
-
//top: $panelPaddingY - 5px;
|
|
346
|
-
}
|
|
338
|
+
.closeButton {}
|
|
347
339
|
|
|
348
340
|
.content {
|
|
349
|
-
//padding: 20px;
|
|
350
341
|
overflow-y: scroll;
|
|
351
342
|
height: 100%;
|
|
352
343
|
}
|
|
@@ -405,6 +396,42 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
405
396
|
transition: $paginationDuration var(--pte-animations-timing-easeOutQuad);
|
|
406
397
|
}
|
|
407
398
|
|
|
399
|
+
// Page transition containers
|
|
400
|
+
.pageStack {
|
|
401
|
+
display: grid;
|
|
402
|
+
grid-template-columns: 1fr;
|
|
403
|
+
min-height: 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.pageStackClip {
|
|
407
|
+
overflow: hidden;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.pageStackItem {
|
|
411
|
+
grid-area: 1 / 1;
|
|
412
|
+
|
|
413
|
+
&[data-active='false'] {
|
|
414
|
+
pointer-events: none;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Progress bar
|
|
419
|
+
.progressBar {
|
|
420
|
+
position: relative;
|
|
421
|
+
width: 100%;
|
|
422
|
+
height: 2px;
|
|
423
|
+
background: var(--pte-new-colors-borderMedium);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.progressBarFill {
|
|
427
|
+
position: absolute;
|
|
428
|
+
top: 0;
|
|
429
|
+
left: 0;
|
|
430
|
+
height: 100%;
|
|
431
|
+
background: var(--pte-new-colors-contentPrimary);
|
|
432
|
+
transition: width $paginationDuration var(--pte-animations-timing-easeInQuad);
|
|
433
|
+
}
|
|
434
|
+
|
|
408
435
|
.bottomPanel {
|
|
409
436
|
border-top: 1px solid var(--pte-new-colors-borderStrong);
|
|
410
437
|
position: absolute;
|
|
@@ -412,6 +439,21 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
412
439
|
width: 100%;
|
|
413
440
|
}
|
|
414
441
|
|
|
442
|
+
.bottomPanelSlots {
|
|
443
|
+
display: flex;
|
|
444
|
+
flex-direction: column;
|
|
445
|
+
|
|
446
|
+
// Auto-separator between portaled slot items
|
|
447
|
+
> * + * {
|
|
448
|
+
border-top: 1px solid var(--pte-new-colors-borderMedium);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Separator between slots and base bottomPanel content that follows
|
|
452
|
+
&:not(:empty) ~ * {
|
|
453
|
+
border-top: 1px solid var(--pte-new-colors-borderMedium);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
415
457
|
.bottomPanelContent {
|
|
416
458
|
position: relative;
|
|
417
459
|
padding: 20px;
|
|
@@ -421,13 +463,12 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
421
463
|
}
|
|
422
464
|
}
|
|
423
465
|
|
|
424
|
-
.
|
|
466
|
+
.bottomPanelSlotItem {
|
|
467
|
+
position: relative;
|
|
425
468
|
padding: 20px;
|
|
469
|
+
}
|
|
426
470
|
|
|
427
|
-
|
|
428
|
-
padding: 0;
|
|
429
|
-
}
|
|
430
|
-
|
|
471
|
+
.bottomPanelSpacer {
|
|
431
472
|
opacity: 0;
|
|
432
473
|
pointer-events: none;
|
|
433
474
|
}
|