Skip to content

Commit c079e38

Browse files
authored
fix(FileInput): add text ellipsis for long filenames (#237)
1 parent 4578e97 commit c079e38

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

.changeset/curly-students-tickle.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cube-dev/ui-kit": patch
3+
---
4+
5+
Add ellipsis for long filenames in FileInput and prevent wrapping.

src/components/forms/FileInput/FileInput.stories.tsx

+41-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import { Story } from '@storybook/react';
2+
import { userEvent, within, waitFor } from '@storybook/testing-library';
3+
14
import { baseProps } from '../../../stories/lists/baseProps';
25

36
import { FileInput } from './FileInput';
47

8+
import type { CubeFileInputProps } from './FileInput';
9+
510
export default {
611
title: 'Forms/FileInput',
712
component: FileInput,
@@ -12,9 +17,43 @@ export default {
1217
},
1318
};
1419

15-
const Template = ({ icon, ...props }) => (
16-
<FileInput {...props} onChange={(query) => console.log('change', query)} />
20+
const Template: Story<CubeFileInputProps> = (props) => (
21+
<FileInput
22+
qa="FileInput"
23+
{...props}
24+
onChange={(value) => console.log('onChange', value)}
25+
/>
1726
);
1827

1928
export const Default = Template.bind({});
2029
Default.args = {};
30+
31+
export const LongFilePlaceholderOverflow = Template.bind({});
32+
LongFilePlaceholderOverflow.args = {
33+
inputStyles: {
34+
width: '300px',
35+
},
36+
placeholder: 'Very long placeholder here',
37+
};
38+
39+
export const LongFileNameOverflow = Template.bind({});
40+
LongFileNameOverflow.args = {
41+
inputStyles: {
42+
width: '300px',
43+
},
44+
inputProps: {
45+
title: 'Test input',
46+
},
47+
};
48+
49+
LongFileNameOverflow.play = async ({ canvasElement }) => {
50+
const canvas = within(canvasElement);
51+
const input = await canvas.getByTitle('Test input');
52+
const file = new File(['test'], 'file-with-a-very-long-name.txt', {
53+
type: 'text/plain',
54+
});
55+
56+
await waitFor(async () => {
57+
await userEvent.upload(input, file);
58+
});
59+
};

src/components/forms/FileInput/FileInput.tsx

+24-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import {
1414
BaseProps,
1515
BlockStyleProps,
1616
CONTAINER_STYLES,
17+
ContainerStyleProps,
1718
extractStyles,
1819
PositionStyleProps,
20+
Props,
1921
Styles,
2022
tasty,
2123
} from '../../../tasty';
@@ -41,6 +43,7 @@ const FileInputElement = tasty(Action, {
4143
radius: true,
4244
cursor: 'pointer',
4345
overflow: 'hidden',
46+
whiteSpace: 'nowrap',
4447

4548
Button: {
4649
radius: true,
@@ -64,10 +67,18 @@ const FileInputElement = tasty(Action, {
6467

6568
Placeholder: {
6669
color: '#dark-02',
70+
whiteSpace: 'nowrap',
71+
textOverflow: 'ellipsis',
72+
width: 'max 100%',
73+
overflow: 'hidden',
6774
},
6875

6976
Value: {
7077
color: '#dark-02',
78+
whiteSpace: 'nowrap',
79+
textOverflow: 'ellipsis',
80+
width: 'max 100%',
81+
overflow: 'hidden',
7182
},
7283

7384
Input: {
@@ -77,7 +88,7 @@ const FileInputElement = tasty(Action, {
7788
bottom: 0,
7889
left: 0,
7990
radius: '@content-radius',
80-
// opacity: 0,
91+
opacity: 0.01,
8192
cursor: 'pointer',
8293
zIndex: 10,
8394
},
@@ -87,6 +98,7 @@ const FileInputElement = tasty(Action, {
8798
export interface CubeFileInputProps
8899
extends BaseProps,
89100
PositionStyleProps,
101+
ContainerStyleProps,
90102
BlockStyleProps,
91103
AriaTextFieldProps,
92104
FormFieldProps {
@@ -104,6 +116,8 @@ export interface CubeFileInputProps
104116
* @default file
105117
*/
106118
type?: 'file' | 'text';
119+
/** Direct input props */
120+
inputProps?: Props;
107121
}
108122

109123
function extractContents(element, callback) {
@@ -147,6 +161,7 @@ function FileInput(props: CubeFileInputProps, ref) {
147161
inputStyles,
148162
labelSuffix,
149163
type = 'file',
164+
inputProps,
150165
...otherProps
151166
} = useProviderProps(props);
152167
const [value, setValue] = useState();
@@ -185,6 +200,11 @@ function FileInput(props: CubeFileInputProps, ref) {
185200
},
186201
}));
187202

203+
const fileName =
204+
typeof value === 'string'
205+
? (value as string).split('\\')?.pop()
206+
: undefined;
207+
188208
const fileInput = (
189209
<FileInputElement
190210
ref={domRef}
@@ -218,10 +238,11 @@ function FileInput(props: CubeFileInputProps, ref) {
218238
onDrop={() => {
219239
setDragHover(false);
220240
}}
241+
{...inputProps}
221242
/>
222243
<div data-element="Button">Choose file</div>
223-
<div data-element={!!value ? 'Value' : 'Placeholder'}>
224-
{value || placeholder || 'No file selected'}
244+
<div data-element={!!fileName ? 'Value' : 'Placeholder'}>
245+
{fileName || placeholder || 'No file selected'}
225246
</div>
226247
</FileInputElement>
227248
);

0 commit comments

Comments
 (0)