Skip to content

Commit 5f6b2b7

Browse files
authored
Merge pull request #97 from toggle-corp/fix/table-dismounting
Fix/table dismounting
2 parents 6b6933e + a2a9cb0 commit 5f6b2b7

12 files changed

Lines changed: 283 additions & 251 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@togglecorp/toggle-ui",
3-
"version": "0.17.0",
3+
"version": "0.18.3",
44
"description": "React component library by togglecorp",
55
"files": [
66
"/build"

src/components/Checkbox/index.tsx

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import styles from './styles.css';
1010

1111
export interface CheckboxProps<N> {
1212
className?: string;
13+
labelContainerClassName?: string;
1314
labelClassName?: string;
1415
checkmark?: (p: CheckmarkProps) => React.ReactElement;
1516
checkmarkClassName?: string;
@@ -22,6 +23,10 @@ export interface CheckboxProps<N> {
2223
value: boolean | undefined | null;
2324
onChange: (value: boolean, name: N) => void;
2425
name: N;
26+
errorContainerClassName?: string;
27+
hintContainerClassName?: string;
28+
error?: string;
29+
hint?: React.ReactNode;
2530
}
2631

2732
function Checkbox<N extends string | number>(props: CheckboxProps<N>) {
@@ -30,6 +35,7 @@ function Checkbox<N extends string | number>(props: CheckboxProps<N>) {
3035
tooltip,
3136
checkmark: Checkmark = DefaultCheckmark,
3237
className: classNameFromProps,
38+
labelContainerClassName,
3339
value,
3440
disabled,
3541
readOnly,
@@ -39,6 +45,10 @@ function Checkbox<N extends string | number>(props: CheckboxProps<N>) {
3945
indeterminate,
4046
uiMode,
4147
name,
48+
error,
49+
hint,
50+
errorContainerClassName,
51+
hintContainerClassName,
4252
...otherProps
4353
} = props;
4454

@@ -54,7 +64,7 @@ function Checkbox<N extends string | number>(props: CheckboxProps<N>) {
5464

5565
const className = _cs(
5666
styles.checkbox,
57-
classNameFromProps,
67+
labelContainerClassName,
5868
indeterminate && styles.indeterminate,
5969
!indeterminate && value && styles.checked,
6070
disabled && styles.disabled,
@@ -63,32 +73,48 @@ function Checkbox<N extends string | number>(props: CheckboxProps<N>) {
6373
);
6474

6575
return (
66-
<label // eslint-disable-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for
67-
className={className}
68-
title={tooltip}
76+
<div
77+
className={_cs(styles.container, classNameFromProps)}
6978
>
70-
<VisualFeedback
71-
disabled={disabled}
72-
readOnly={readOnly}
73-
/>
74-
<Checkmark
75-
className={_cs(checkmarkClassName, styles.checkmark)}
76-
value={value ?? false}
77-
indeterminate={indeterminate}
78-
uiMode={uiMode}
79-
/>
80-
<input
81-
onChange={handleChange}
82-
className={styles.input}
83-
type="checkbox"
84-
checked={value ?? false}
85-
disabled={disabled || readOnly}
86-
{...otherProps}
87-
/>
88-
<div className={_cs(styles.label, labelClassName)}>
89-
{ label }
90-
</div>
91-
</label>
79+
<label // eslint-disable-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for, max-len
80+
className={className}
81+
title={tooltip}
82+
>
83+
<VisualFeedback
84+
disabled={disabled}
85+
readOnly={readOnly}
86+
/>
87+
<Checkmark
88+
className={_cs(checkmarkClassName, styles.checkmark)}
89+
value={value ?? false}
90+
indeterminate={indeterminate}
91+
uiMode={uiMode}
92+
/>
93+
<input
94+
onChange={handleChange}
95+
className={styles.input}
96+
type="checkbox"
97+
checked={value ?? false}
98+
disabled={disabled || readOnly}
99+
{...otherProps}
100+
/>
101+
{label && (
102+
<div className={_cs(styles.label, labelClassName)}>
103+
{ label }
104+
</div>
105+
)}
106+
</label>
107+
{error && (
108+
<div className={_cs(styles.error, errorContainerClassName)}>
109+
{error}
110+
</div>
111+
)}
112+
{!error && hint && (
113+
<div className={_cs(styles.hint, hintContainerClassName)}>
114+
{hint}
115+
</div>
116+
)}
117+
</div>
92118
);
93119
}
94120

src/components/Checkbox/styles.css

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1+
.container {
2+
display: flex;
3+
position: relative;
4+
flex-direction: column;
5+
cursor: pointer;
6+
gap: var(--tui-spacing-extra-small);
7+
padding: var(--tui-spacing-extra-small);
8+
9+
.hint {
10+
color: var(--color-hint);
11+
font-size: var(--tui-font-size-small);
12+
}
13+
14+
.error {
15+
color: var(--tui-color-danger);
16+
font-size: var(--tui-font-size-small);
17+
}
18+
}
19+
120
.checkbox {
221
--color-text: transparent;
322
--color-checkmark: transparent;
423

524
display: flex;
6-
position: relative;
725
align-items: center;
8-
cursor: pointer;
9-
padding: calc(var(--tui-spacing-medium) - var(--tui-spacing-extra-small));
1026
color: var(--color-text);
27+
gap: var(--tui-spacing-extra-small);
1128
user-select: none;
1229

1330
.checkmark {
@@ -21,10 +38,6 @@
2138
display: none;
2239
}
2340

24-
.label {
25-
padding: var(--tui-spacing-extra-small);
26-
}
27-
2841
&.light {
2942
--color-text: var(--tui-color-text-light);
3043
--color-checkmark: var(--tui-color-text-light);

src/components/DateInput/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function DateInput<T extends string>(props: Props<T>) {
4545
uiMode,
4646
inputElementRef,
4747
containerRef: containerRefFromProps,
48-
inputSectionRef,
48+
inputSectionRef: inputSectionRefFromProps,
4949
inputClassName,
5050
onChange,
5151
name,
@@ -55,9 +55,11 @@ function DateInput<T extends string>(props: Props<T>) {
5555

5656
const [calendarMonthSelectionPopupClassName] = React.useState(randomString(16));
5757
const createdContainerRef = React.useRef<HTMLDivElement>(null);
58+
const createdInputSectionRef = React.useRef<HTMLDivElement>(null);
5859
const popupRef = React.useRef<HTMLDivElement>(null);
5960

6061
const containerRef = containerRefFromProps ?? createdContainerRef;
62+
const inputSectionRef = inputSectionRefFromProps ?? createdInputSectionRef;
6163

6264
const [
6365
showCalendar,
@@ -88,7 +90,7 @@ function DateInput<T extends string>(props: Props<T>) {
8890
showCalendar,
8991
handlePopupBlur,
9092
popupRef,
91-
containerRef,
93+
inputSectionRef,
9294
);
9395

9496
const handleCalendarDateClick: CalendarProps<CalendarDateProps>['onDateClick'] = React.useCallback(
@@ -185,7 +187,7 @@ function DateInput<T extends string>(props: Props<T>) {
185187
/>
186188
{!readOnly && showCalendar && (
187189
<Popup
188-
parentRef={containerRef}
190+
parentRef={inputSectionRef}
189191
elementRef={popupRef}
190192
className={styles.calendarPopup}
191193
contentClassName={styles.popupContent}

src/components/DateRangeInput/index.tsx

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import {
33
_cs,
44
randomString,
55
isDefined,
6+
isNotDefined,
67
} from '@togglecorp/fujs';
78
import {
89
IoCalendarOutline,
@@ -98,6 +99,7 @@ export interface Props<N extends NameType> extends InheritedProps {
9899
value: Value | undefined | null;
99100
name: N;
100101
onChange?: (value: Value | undefined, name: N) => void;
102+
placeholder?: string;
101103
}
102104

103105
function DateRangeInput<N extends NameType>(props: Props<N>) {
@@ -119,11 +121,12 @@ function DateRangeInput<N extends NameType>(props: Props<N>) {
119121
uiMode,
120122
inputElementRef,
121123
containerRef: containerRefFromProps,
122-
inputSectionRef,
124+
inputSectionRef: inputSectionRefFromProps,
123125
inputClassName,
124126
onChange,
125127
name,
126128
value,
129+
placeholder,
127130
} = props;
128131

129132
const [tempDate, setTempDate] = React.useState<Partial<Value>>({
@@ -132,9 +135,11 @@ function DateRangeInput<N extends NameType>(props: Props<N>) {
132135
});
133136
const [calendarMonthSelectionPopupClassName] = React.useState(randomString(16));
134137
const createdContainerRef = React.useRef<HTMLDivElement>(null);
138+
const createdInputSectionRef = React.useRef<HTMLDivElement>(null);
135139
const popupRef = React.useRef<HTMLDivElement>(null);
136140

137141
const containerRef = containerRefFromProps ?? createdContainerRef;
142+
const inputSectionRef = inputSectionRefFromProps ?? createdInputSectionRef;
138143
const [
139144
showCalendar,
140145
setShowCalendarTrue,
@@ -171,7 +176,7 @@ function DateRangeInput<N extends NameType>(props: Props<N>) {
171176
showCalendar,
172177
handlePopupBlur,
173178
popupRef,
174-
containerRef,
179+
inputSectionRef,
175180
);
176181

177182
const dateRendererParams = React.useCallback(() => ({
@@ -276,6 +281,33 @@ function DateRangeInput<N extends NameType>(props: Props<N>) {
276281
1,
277282
);
278283

284+
const dateInputLabel = useMemo(
285+
() => {
286+
if (
287+
isNotDefined(tempDate.startDate)
288+
&& isNotDefined(value?.startDate)
289+
&& isNotDefined(value?.endDate)
290+
) {
291+
return undefined;
292+
}
293+
294+
const startDateString = tempDate.startDate ?? value?.startDate;
295+
const start = isDefined(startDateString)
296+
? new Date(startDateString).toLocaleDateString()
297+
: '--';
298+
const endDateString = value?.endDate;
299+
const end = isDefined(endDateString)
300+
? new Date(endDateString).toLocaleDateString()
301+
: '--';
302+
303+
return [
304+
start,
305+
end,
306+
].join(' to ');
307+
},
308+
[value, tempDate],
309+
);
310+
279311
return (
280312
<>
281313
<InputContainer
@@ -328,55 +360,30 @@ function DateRangeInput<N extends NameType>(props: Props<N>) {
328360
readOnly={readOnly}
329361
uiMode={uiMode}
330362
input={(
331-
<>
332-
<RawInput<string>
333-
name="startDate"
334-
className={_cs(
335-
styles.input,
336-
styles.startDateInput,
337-
!!error && styles.errored,
338-
!(tempDate.startDate ?? value?.startDate) && styles.empty,
339-
inputClassName,
340-
)}
341-
value={tempDate.startDate ?? value?.startDate}
342-
// NOTE: Make this required to hide clear button on firefox
343-
required={!!(tempDate.startDate ?? value?.startDate)}
344-
elementRef={inputElementRef}
345-
readOnly
346-
uiMode={uiMode}
347-
disabled={disabled}
348-
onFocus={setShowCalendarTrue}
349-
type="date"
350-
/>
351-
<div className={styles.separator}>
352-
to
353-
</div>
354-
<RawInput<string>
355-
name="startDate"
356-
className={_cs(
357-
styles.input,
358-
styles.endDateInput,
359-
!!error && styles.errored,
360-
!value?.endDate && styles.empty,
361-
inputClassName,
362-
)}
363-
elementRef={inputElementRef}
364-
readOnly
365-
onClick={setShowCalendarTrue}
366-
// NOTE: Make this required to hide clear button on firefox
367-
required={!!value?.endDate}
368-
value={value?.endDate}
369-
uiMode={uiMode}
370-
disabled={disabled}
371-
onFocus={setShowCalendarTrue}
372-
type="date"
373-
/>
374-
</>
363+
<RawInput
364+
elementRef={inputElementRef}
365+
name="date-range"
366+
value={dateInputLabel}
367+
readOnly
368+
uiMode={uiMode}
369+
disabled={disabled}
370+
onFocus={setShowCalendarTrue}
371+
onClick={setShowCalendarTrue}
372+
className={_cs(
373+
styles.input,
374+
!!error && styles.errored,
375+
!(tempDate.startDate || value?.startDate || value?.endDate)
376+
&& styles.empty,
377+
inputClassName,
378+
)}
379+
type="text"
380+
placeholder={placeholder}
381+
/>
375382
)}
376383
/>
377384
{!readOnly && showCalendar && (
378385
<Popup
379-
parentRef={containerRef}
386+
parentRef={inputSectionRef}
380387
elementRef={popupRef}
381388
freeWidth
382389
className={styles.calendarPopup}

0 commit comments

Comments
 (0)