Skip to content

Commit 9ed0e20

Browse files
authored
fix: unify input width (#108)
* fix: unify input width * fix: input bg * docs: fix demo * docs: tweak file structure
1 parent 691f18c commit 9ed0e20

30 files changed

Lines changed: 969 additions & 394 deletions

apps/docs/src/containers/theme-studio/editor-fields.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,30 @@ export function swatchTextStyle(background: string, foreground: string): React.C
1010
}
1111

1212
function parseSliderValue(value: string, unit?: 'px' | 'em' | 'rem'): number | undefined {
13+
const trimmed = value.trim();
14+
15+
// CSS zero is unit-agnostic. Presets may serialize it as `0px` while the
16+
// editor slider expects `rem`, so normalize all zero forms to numeric 0.
17+
if (/^-?0(?:\.0+)?(?:px|em|rem)?$/.test(trimmed)) {
18+
return 0;
19+
}
20+
1321
if (unit === 'px') {
14-
const match = /^(-?\d+(?:\.\d+)?)px$/.exec(value.trim());
22+
const match = /^(-?\d+(?:\.\d+)?)px$/.exec(trimmed);
1523
return match ? Number(match[1]) : undefined;
1624
}
1725

1826
if (unit === 'em') {
19-
const match = /^(-?\d+(?:\.\d+)?)em$/.exec(value.trim());
27+
const match = /^(-?\d+(?:\.\d+)?)em$/.exec(trimmed);
2028
return match ? Number(match[1]) : undefined;
2129
}
2230

2331
if (unit === 'rem') {
24-
const match = /^(-?\d+(?:\.\d+)?)rem$/.exec(value.trim());
32+
const match = /^(-?\d+(?:\.\d+)?)rem$/.exec(trimmed);
2533
return match ? Number(match[1]) : undefined;
2634
}
2735

28-
const parsed = Number(value);
36+
const parsed = Number(trimmed);
2937
return Number.isNaN(parsed) ? undefined : parsed;
3038
}
3139

apps/docs/src/containers/theme-studio/theme-document-adapter.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,21 @@ export function buildThemeDocumentFromDraft(draft: ThemeEditorDraft): ThemeDocum
245245
'cascader.height.sm': fields.fieldHeightSm,
246246
'cascader.height.md': fields.fieldHeightMd,
247247
'cascader.height.lg': fields.fieldHeightLg,
248+
'cascader.bg': fields.base,
249+
'cascader.border': fields.input,
250+
'cascader.border-hover': fields.ring,
251+
'cascader.border-focus': fields.ring,
252+
'cascader.shadow-focus': fields.shadowFocus,
253+
'cascader.radius': fields.inputRadius,
248254
'cascader.padding.sm': `0 calc(${fields.fieldPaddingSm} + 20px) 0 ${fields.fieldPaddingSm}`,
249255
'cascader.padding.md': `0 calc(${fields.fieldPaddingMd} + 20px) 0 ${fields.fieldPaddingMd}`,
250256
'cascader.padding.lg': `0 calc(${fields.fieldPaddingLg} + 20px) 0 ${fields.fieldPaddingLg}`,
257+
'native-select.bg': fields.base,
258+
'native-select.border': fields.input,
259+
'native-select.border-hover': fields.ring,
260+
'native-select.border-focus': fields.ring,
261+
'native-select.shadow-focus': fields.shadowFocus,
262+
'native-select.radius': fields.inputRadius,
251263
'checkbox.bg': fields.base,
252264
'checkbox.border': fields.input,
253265
'checkbox.border.hover': fields.ring,

packages/react/src/cascader/style/index.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
.#{$prefix}-cascader {
44
position: relative;
55
display: inline-block;
6-
min-width: var(--ty-cascader-min-width);
6+
width: 100%;
7+
min-width: 0;
78

89
&_disabled {
910
opacity: var(--ty-cascader-opacity-disabled);

packages/react/src/date-picker/style/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ $dp: #{$prefix}-date-picker;
55
.#{$dp} {
66
display: inline-flex;
77
position: relative;
8+
width: 100%;
89
font-size: var(--ty-picker-input-font-size);
910

1011
// ---- Input ----
Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,72 @@
11
import React from 'react';
2-
import { Button, Grid } from '@tiny-design/react';
2+
import { Grid, Radio } from '@tiny-design/react';
3+
import { DemoControlLabel, DemoControls, getDemoBlockStyle } from './shared';
4+
5+
type AlignmentValue = 'start' | 'center' | 'end' | 'stretch';
36

47
export default function AlignmentGridDemo() {
8+
const [justify, setJustify] = React.useState<AlignmentValue>('stretch');
9+
const [align, setAlign] = React.useState<AlignmentValue>('stretch');
10+
511
return (
6-
<Grid
7-
columns={3}
8-
gap="sm"
9-
align="center"
10-
justify="center"
11-
style={{
12-
minHeight: 180,
13-
padding: 16,
14-
border: '1px dashed var(--ty-color-border)',
15-
borderRadius: 12,
16-
background:
17-
'linear-gradient(180deg, color-mix(in srgb, var(--ty-color-primary) 6%, transparent), color-mix(in srgb, var(--ty-color-primary-bg) 45%, transparent))',
18-
}}>
19-
<Button variant="solid" color="primary">
20-
Primary
21-
</Button>
22-
<Button>Default</Button>
23-
<Button variant="outline" color="primary">
24-
Outline
25-
</Button>
26-
</Grid>
12+
<div>
13+
<DemoControls>
14+
<div>
15+
<DemoControlLabel>Justify</DemoControlLabel>
16+
<Radio.Group value={justify} onChange={(val) => setJustify(val as AlignmentValue)}>
17+
<Radio value="start">start</Radio>
18+
<Radio value="center">center</Radio>
19+
<Radio value="end">end</Radio>
20+
<Radio value="stretch">stretch</Radio>
21+
</Radio.Group>
22+
</div>
23+
<div>
24+
<DemoControlLabel>Align</DemoControlLabel>
25+
<Radio.Group value={align} onChange={(val) => setAlign(val as AlignmentValue)}>
26+
<Radio value="start">start</Radio>
27+
<Radio value="center">center</Radio>
28+
<Radio value="end">end</Radio>
29+
<Radio value="stretch">stretch</Radio>
30+
</Radio.Group>
31+
</div>
32+
</DemoControls>
33+
<Grid
34+
columns={3}
35+
gap="sm"
36+
align={align}
37+
justify={justify}
38+
style={{
39+
minHeight: 180,
40+
padding: 16,
41+
border: '1px dashed var(--ty-color-border)',
42+
borderRadius: 12,
43+
background: 'color-mix(in srgb, var(--ty-color-primary) 4%, transparent)',
44+
}}>
45+
<div
46+
style={getDemoBlockStyle('strong', 64, {
47+
minHeight: 64,
48+
width: justify === 'stretch' ? undefined : 92,
49+
justifyContent: 'center',
50+
})}>
51+
{justify}
52+
</div>
53+
<div
54+
style={getDemoBlockStyle('base', 64, {
55+
minHeight: 64,
56+
width: justify === 'stretch' ? undefined : 92,
57+
justifyContent: 'center',
58+
})}>
59+
{align}
60+
</div>
61+
<div
62+
style={getDemoBlockStyle('soft', 64, {
63+
minHeight: 64,
64+
width: justify === 'stretch' ? undefined : 92,
65+
justifyContent: 'center',
66+
})}>
67+
items
68+
</div>
69+
</Grid>
70+
</div>
2771
);
2872
}
Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,72 @@
11
import React from 'react';
2-
import { Card, Grid } from '@tiny-design/react';
2+
import { Checkbox, Grid, Slider } from '@tiny-design/react';
3+
import type { SliderValue } from '@tiny-design/react';
4+
import { DemoBlock, DemoControlLabel, DemoControls } from './shared';
35

46
export default function AutoFitDemo() {
7+
const [minColumnWidth, setMinColumnWidth] = React.useState(180);
8+
const [autoFit, setAutoFit] = React.useState(true);
9+
const [count, setCount] = React.useState(5);
10+
511
return (
6-
<Grid minColumnWidth={180} gap="sm">
7-
{['Analytics', 'Revenue', 'Orders', 'Retention', 'Conversion'].map((title) => (
8-
<Card key={title}>
9-
<Card.Content>
10-
<strong>{title}</strong>
11-
<div style={{ marginTop: 8, color: 'var(--ty-color-text-secondary)' }}>Auto-fit cards without manual breakpoints.</div>
12-
</Card.Content>
13-
</Card>
14-
))}
15-
</Grid>
12+
<div>
13+
<DemoControls>
14+
<div>
15+
<DemoControlLabel>Min column width: {minColumnWidth}px</DemoControlLabel>
16+
<Slider
17+
min={140}
18+
max={260}
19+
step={20}
20+
value={minColumnWidth}
21+
onChange={(val: SliderValue) => {
22+
if (typeof val === 'number') {
23+
setMinColumnWidth(val);
24+
}
25+
}}
26+
/>
27+
</div>
28+
<div>
29+
<DemoControlLabel>Item count: {count}</DemoControlLabel>
30+
<Slider
31+
min={4}
32+
max={8}
33+
step={1}
34+
value={count}
35+
onChange={(val: SliderValue) => {
36+
if (typeof val === 'number') {
37+
setCount(val);
38+
}
39+
}}
40+
/>
41+
</div>
42+
<div>
43+
<Checkbox
44+
checked={autoFit}
45+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAutoFit(e.currentTarget.checked)}>
46+
Use auto-fit
47+
</Checkbox>
48+
</div>
49+
</DemoControls>
50+
<Grid minColumnWidth={minColumnWidth} autoFit={autoFit} gap="sm">
51+
{[
52+
['Analytics', `${autoFit ? 'auto-fit' : 'auto-fill'} / ${minColumnWidth}px`],
53+
['Revenue', 'responsive tracks'],
54+
['Orders', 'reflow'],
55+
['Retention', 'no breakpoints'],
56+
['Conversion', 'fluid blocks'],
57+
['Traffic', 'auto placement'],
58+
['Pipeline', 'repeat tracks'],
59+
['Forecast', 'adaptive cells'],
60+
].slice(0, count).map(([title, detail], index) => (
61+
<DemoBlock
62+
key={title}
63+
title={title}
64+
detail={detail}
65+
tone={index % 2 === 0 ? 'strong' : 'soft'}
66+
minHeight={96}
67+
/>
68+
))}
69+
</Grid>
70+
</div>
1671
);
1772
}

0 commit comments

Comments
 (0)