@janbox/storefront-ui 2.0.29 → 2.0.31
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/README.md +692 -0
- package/dist/lib/accordion/README.md +81 -0
- package/dist/lib/avatar/README.md +74 -0
- package/dist/lib/badge/README.md +58 -0
- package/dist/lib/box/README.md +69 -0
- package/dist/lib/breadcrumbs/README.md +70 -0
- package/dist/lib/button/README.md +115 -0
- package/dist/lib/cascader/README.md +128 -0
- package/dist/lib/checkbox/README.md +74 -0
- package/dist/lib/checkbox/checkbox.js +107 -12
- package/dist/lib/checkbox/types.d.ts +2 -2
- package/dist/lib/chip/README.md +72 -0
- package/dist/lib/collapse/README.md +78 -0
- package/dist/lib/container/README.md +59 -0
- package/dist/lib/count-up/README.md +52 -0
- package/dist/lib/countdown-timer/README.md +77 -0
- package/dist/lib/date-picker/README.md +94 -0
- package/dist/lib/dialog/README.md +109 -0
- package/dist/lib/drawer/README.md +97 -0
- package/dist/lib/filter-panel/README.md +146 -0
- package/dist/lib/flag/README.md +58 -0
- package/dist/lib/flexbox/README.md +59 -0
- package/dist/lib/floating/README.md +109 -0
- package/dist/lib/form-helper-text/README.md +54 -0
- package/dist/lib/form-label/README.md +50 -0
- package/dist/lib/grid/README.md +72 -0
- package/dist/lib/highlight-words/README.md +64 -0
- package/dist/lib/highlight-words/highlight-words.js +1 -2
- package/dist/lib/icon/README.md +69 -0
- package/dist/lib/icon-button/README.md +92 -0
- package/dist/lib/image/README.md +80 -0
- package/dist/lib/input/README.md +118 -0
- package/dist/lib/input-mask/README.md +88 -0
- package/dist/lib/input-number/README.md +92 -0
- package/dist/lib/input-range/README.md +85 -0
- package/dist/lib/lightbox/README.md +107 -0
- package/dist/lib/linear-progress/README.md +54 -0
- package/dist/lib/link/README.md +67 -0
- package/dist/lib/loading/README.md +65 -0
- package/dist/lib/marquee/README.md +83 -0
- package/dist/lib/marquee/marquee/marquee.js +1 -1
- package/dist/lib/menu/README.md +92 -0
- package/dist/lib/multiple-select/README.md +108 -0
- package/dist/lib/nav-link/README.md +61 -0
- package/dist/lib/notifications/README.md +103 -0
- package/dist/lib/otp-input/README.md +71 -0
- package/dist/lib/pagination/README.md +84 -0
- package/dist/lib/phone-input/README.md +80 -0
- package/dist/lib/popover/README.md +93 -0
- package/dist/lib/price-label/README.md +78 -0
- package/dist/lib/primitive/README.md +80 -0
- package/dist/lib/progress/README.md +50 -0
- package/dist/lib/radio-button/README.md +89 -0
- package/dist/lib/radio-button/radio-button.js +98 -7
- package/dist/lib/ripple-effect/README.md +66 -0
- package/dist/lib/select/README.md +124 -0
- package/dist/lib/star-rating/README.md +67 -0
- package/dist/lib/stepper/README.md +99 -0
- package/dist/lib/suspense-query/README.md +78 -0
- package/dist/lib/swiper/README.md +99 -0
- package/dist/lib/switch/README.md +73 -0
- package/dist/lib/switch/switch.d.ts +1 -1
- package/dist/lib/switch/switch.js +110 -11
- package/dist/lib/table/README.md +115 -0
- package/dist/lib/tabs/README.md +103 -0
- package/dist/lib/text/README.md +59 -0
- package/dist/lib/textarea/README.md +76 -0
- package/dist/lib/time-picker/README.md +100 -0
- package/dist/lib/tooltip/README.md +106 -0
- package/dist/lib/unordered-list/README.md +85 -0
- package/dist/lib/video/README.md +88 -0
- package/dist/style.css +1 -244
- package/package.json +5 -5
- package/dist/lib/checkbox/checkbox.module.scss.js +0 -23
- package/dist/lib/radio-button/radio-button.module.scss.js +0 -17
- package/dist/lib/switch/switch.module.scss.js +0 -14
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Tabs
|
|
2
|
+
|
|
3
|
+
A compound tabs component for switching between content panels. It manages active tab state (controlled or uncontrolled) and provides context to sub-components: TabList, Tab, TabContent, TabPanel, and TabIndicator.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Tabs } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `activeIndex` | `number` | - | Controlled active tab index. When provided, the component delegates state management to the parent. |
|
|
16
|
+
| `defaultActiveIndex` | `number` | `0` | Initial active tab index for uncontrolled usage. |
|
|
17
|
+
| `onTabChange` | `(tabIndex: number) => void` | - | Callback fired when the active tab changes, receiving the new tab index. |
|
|
18
|
+
| `tabProps` | `Partial<TabProps>` | `{ color: 'neutral', variant: 'text', states: { active: { color: 'primary', variant: 'text' } } }` | Default props applied to every Tab child. Inactive tabs default to `color='neutral'`, active tab overrides to `color='primary'`. |
|
|
19
|
+
| `tabIndicatorProps` | `TabIndicatorProps` | `{ sx: { height: 2, backgroundColor: 'var(--color-primary-600)' } }` | Props forwarded to the TabIndicator element, cho phép custom `sx` styles trên thanh gạch chân của tab đang active. |
|
|
20
|
+
| `tabPanelProps` | `Partial<TabPanelProps>` | - | Default props applied to every TabPanel child. |
|
|
21
|
+
| `preventActiveTabChange` | `boolean` | `true` | Khi `true`, click vào tab đang active sẽ không re-fire `onTabChange`. |
|
|
22
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Responsive Emotion CSS overrides cho root wrapper `div`. |
|
|
23
|
+
| `children` * | `React.ReactNode` | - | Phải là composition của `TabList` (chứa các `Tab`) và `TabContent` (chứa các `TabPanel`). |
|
|
24
|
+
|
|
25
|
+
*Required props
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
### Basic uncontrolled tabs
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<Tabs defaultActiveIndex={0} onTabChange={(i) => console.log(i)} style={{ width: 500 }}>
|
|
33
|
+
<TabList>
|
|
34
|
+
<Tab>Tab 1</Tab>
|
|
35
|
+
<Tab>Tab 2</Tab>
|
|
36
|
+
<Tab>Tab 3</Tab>
|
|
37
|
+
</TabList>
|
|
38
|
+
<TabContent>
|
|
39
|
+
<TabPanel>Content for Tab 1</TabPanel>
|
|
40
|
+
<TabPanel>Content for Tab 2</TabPanel>
|
|
41
|
+
<TabPanel>Content for Tab 3</TabPanel>
|
|
42
|
+
</TabContent>
|
|
43
|
+
</Tabs>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Controlled tabs with second tab active by default
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
const [active, setActive] = useState(1);
|
|
50
|
+
|
|
51
|
+
<Tabs activeIndex={active} onTabChange={setActive} style={{ width: 500 }}>
|
|
52
|
+
<TabList>
|
|
53
|
+
<Tab>Overview</Tab>
|
|
54
|
+
<Tab>Details</Tab>
|
|
55
|
+
<Tab>Reviews</Tab>
|
|
56
|
+
</TabList>
|
|
57
|
+
<TabContent>
|
|
58
|
+
<TabPanel>Overview content</TabPanel>
|
|
59
|
+
<TabPanel>Details content</TabPanel>
|
|
60
|
+
<TabPanel>Reviews content</TabPanel>
|
|
61
|
+
</TabContent>
|
|
62
|
+
</Tabs>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Custom tab color and variant via tabProps
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
<Tabs
|
|
69
|
+
defaultActiveIndex={0}
|
|
70
|
+
tabProps={{ color: 'primary', variant: 'text' }}
|
|
71
|
+
style={{ width: 500 }}
|
|
72
|
+
>
|
|
73
|
+
<TabList>
|
|
74
|
+
<Tab>Home</Tab>
|
|
75
|
+
<Tab>Profile</Tab>
|
|
76
|
+
<Tab>Settings</Tab>
|
|
77
|
+
</TabList>
|
|
78
|
+
<TabContent>
|
|
79
|
+
<TabPanel>Home content</TabPanel>
|
|
80
|
+
<TabPanel>Profile content</TabPanel>
|
|
81
|
+
<TabPanel>Settings content</TabPanel>
|
|
82
|
+
</TabContent>
|
|
83
|
+
</Tabs>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Related Components
|
|
87
|
+
|
|
88
|
+
- [TabList](../tablist/README.md)
|
|
89
|
+
- [Tab](../tab/README.md)
|
|
90
|
+
- [TabContent](../tabcontent/README.md)
|
|
91
|
+
- [TabPanel](../tabpanel/README.md)
|
|
92
|
+
- [TabIndicator](../tabindicator/README.md)
|
|
93
|
+
- [Button](../button/README.md)
|
|
94
|
+
|
|
95
|
+
## Dependencies
|
|
96
|
+
|
|
97
|
+
- @emotion/react
|
|
98
|
+
|
|
99
|
+
## See Also
|
|
100
|
+
|
|
101
|
+
- [Component Source](./index.ts)
|
|
102
|
+
- [Storybook Stories](./tabs.stories.tsx)
|
|
103
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Text
|
|
2
|
+
|
|
3
|
+
A polymorphic text component for rendering text content with responsive typography sizing. Supports multiple typography size variants and can render as any HTML element.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Text } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `sizeVariant` | `TypographySizeVariant` | - | Typography size variant. Options: `'xs'` \| `'sm'` \| `'base'` \| `'lg'` \| `'xl'` \| `'2xl'` \| `'3xl'` \| `'4xl'` \| `'5xl'` \| `'6xl'` |
|
|
16
|
+
| `as` | `HTMLElementType` | `p` | HTML element type to render as (e.g., `'p'`, `'span'`, `'div'`, `'h1'`) |
|
|
17
|
+
| `children` | `React.ReactNode` | - | Text content to display |
|
|
18
|
+
| `dangerouslySetInnerHTML` | `{ __html: string }` | - | Renders HTML string directly (use with caution) |
|
|
19
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Emotion CSS styles with responsive breakpoint support (`sm`, `md`, `lg`) |
|
|
20
|
+
| `sm` | `TextResponsiveProps` | - | Responsive props for small breakpoint (768px+) |
|
|
21
|
+
| `md` | `TextResponsiveProps` | - | Responsive props for medium breakpoint (1280px+) |
|
|
22
|
+
| `lg` | `TextResponsiveProps` | - | Responsive props for large breakpoint (1680px+) |
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### Basic paragraph text
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<Text>Default paragraph text</Text>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Large heading with custom element
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<Text as="h1" sizeVariant="6xl">Main Heading</Text>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Responsive text sizing
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<Text sizeVariant="sm" sm={{ sizeVariant: 'base' }} md={{ sizeVariant: 'lg' }}>
|
|
42
|
+
Responsive text that grows on larger screens
|
|
43
|
+
</Text>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Related Components
|
|
47
|
+
|
|
48
|
+
- [Primitive](../primitive/README.md)
|
|
49
|
+
|
|
50
|
+
## Dependencies
|
|
51
|
+
|
|
52
|
+
- @emotion/react
|
|
53
|
+
- lodash-es
|
|
54
|
+
|
|
55
|
+
## See Also
|
|
56
|
+
|
|
57
|
+
- [Component Source](./index.ts)
|
|
58
|
+
- [Storybook Stories](./text.stories.tsx)
|
|
59
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Textarea
|
|
2
|
+
|
|
3
|
+
A multi-line text input component with support for debounced onChange, onBlur mode, helper text, error states, and responsive sizing. Wraps a native textarea element with enhanced styling and validation.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Textarea } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `size` | `SizeVariant` | `md` | Size variant controlling padding and typography. Options: `'xs' \| 'sm' \| 'md' \| 'lg'` |
|
|
16
|
+
| `containerProps` | `PropsWithSx<JSX.IntrinsicElements['div']>` | - | Props for the outermost container div wrapper |
|
|
17
|
+
| `mainProps` | `PrimitiveProps<JSX.IntrinsicElements['div']>` | - | Props for the main wrapper div that contains the textarea (includes border, padding, focus states) |
|
|
18
|
+
| `helperText` | `string` | - | Helper text displayed below the textarea (uses FormHelperText component) |
|
|
19
|
+
| `error` | `boolean` | - | Error state - displays red border and renders helperText in error style |
|
|
20
|
+
| `value` | `string` | - | Controlled value for the textarea |
|
|
21
|
+
| `defaultValue` | `string` | - | Uncontrolled default value for the textarea |
|
|
22
|
+
| `mode` | `'onChange' \| 'onBlur'` | `'onChange'` | When to trigger onChange callback. `'onChange'` fires immediately, `'onBlur'` fires when focus leaves the textarea |
|
|
23
|
+
| `debounce` | `number` | `0` | Debounce delay in milliseconds before onChange is called. Also triggers onChange on blur if value changed |
|
|
24
|
+
| `onChange` | `(e: React.ChangeEvent<HTMLTextAreaElement>) => void` | - | Change event handler - respects mode and debounce settings |
|
|
25
|
+
| `placeholder` | `string` | - | Placeholder text for the textarea |
|
|
26
|
+
| `disabled` | `boolean` | - | Disables the textarea (styled with gray background and border) |
|
|
27
|
+
| `readOnly` | `boolean` | - | Makes the textarea read-only (pointer events disabled) |
|
|
28
|
+
| `rows` | `number` | - | Number of visible text rows |
|
|
29
|
+
| `className` | `string` | - | Custom class name applied to the textarea element itself |
|
|
30
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Responsive Emotion CSS styles (supports `sm`, `md`, `lg` breakpoints) |
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Basic Usage
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<Textarea placeholder="Enter text..." />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### With Validation
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<Textarea
|
|
44
|
+
placeholder="Enter description..."
|
|
45
|
+
error={true}
|
|
46
|
+
helperText="This field is required"
|
|
47
|
+
/>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Debounced Input
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Textarea
|
|
54
|
+
placeholder="Search..."
|
|
55
|
+
debounce={500}
|
|
56
|
+
onChange={(e) => handleSearch(e.target.value)}
|
|
57
|
+
helperText="Searches as you type (500ms delay)"
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Related Components
|
|
62
|
+
|
|
63
|
+
- [FormHelperText](../formhelpertext/README.md)
|
|
64
|
+
- [Primitive](../primitive/README.md)
|
|
65
|
+
- [Input](../input/README.md)
|
|
66
|
+
|
|
67
|
+
## Dependencies
|
|
68
|
+
|
|
69
|
+
- @floating-ui/react
|
|
70
|
+
- lodash-es
|
|
71
|
+
|
|
72
|
+
## See Also
|
|
73
|
+
|
|
74
|
+
- [Component Source](./index.ts)
|
|
75
|
+
- [Storybook Stories](./textarea.stories.tsx)
|
|
76
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# TimePicker
|
|
2
|
+
|
|
3
|
+
Input chọn giờ và phút — hiển thị dropdown với hai cột scroll ảo (hours 0–23, minutes 0–59).
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { TimePicker } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `value` | `Date \| null` | - | Giá trị được chọn (controlled) |
|
|
16
|
+
| `defaultValue` | `Date` | - | Giá trị mặc định (uncontrolled) |
|
|
17
|
+
| `onChange` | `(date: Date) => void` | - | Callback khi chọn giờ hoặc phút |
|
|
18
|
+
| `placeholder` | `string` | `'--:--'` | Placeholder text khi chưa chọn |
|
|
19
|
+
| `clearable` | `boolean` | - | Hiện nút clear khi đã có giá trị |
|
|
20
|
+
| `onClear` | `() => void` | - | Callback khi nhấn clear |
|
|
21
|
+
| `disabled` | `boolean` | - | Disable input |
|
|
22
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | - | Kích thước — responsive prop |
|
|
23
|
+
| `placement` | `Placement` | `'bottom-start'` | Vị trí dropdown (từ `@floating-ui/react`) |
|
|
24
|
+
| `open` | `boolean` | - | Controlled open state |
|
|
25
|
+
| `onOpenChange` | `UseFloatingOptions['onOpenChange']` | - | Callback khi dropdown mở/đóng |
|
|
26
|
+
| `containerProps` | `PropsWithSx<JSX.IntrinsicElements['div']>` | - | Props cho container div bên ngoài |
|
|
27
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Custom styles cho trigger |
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### Cơ bản — Uncontrolled
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { TimePicker } from '@janbox/storefront-ui';
|
|
35
|
+
|
|
36
|
+
<TimePicker
|
|
37
|
+
placeholder="Chọn giờ"
|
|
38
|
+
onChange={(date) => console.log(date)}
|
|
39
|
+
/>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Controlled
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
const [time, setTime] = useState<Date | null>(null);
|
|
46
|
+
|
|
47
|
+
<TimePicker
|
|
48
|
+
value={time}
|
|
49
|
+
onChange={setTime}
|
|
50
|
+
clearable
|
|
51
|
+
onClear={() => setTime(null)}
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Với default value
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const defaultTime = new Date();
|
|
59
|
+
defaultTime.setHours(9, 30);
|
|
60
|
+
|
|
61
|
+
<TimePicker
|
|
62
|
+
defaultValue={defaultTime}
|
|
63
|
+
onChange={(date) => console.log(date)}
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Trong form
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
71
|
+
<FormLabel>Giờ mở cửa</FormLabel>
|
|
72
|
+
<TimePicker
|
|
73
|
+
value={openTime}
|
|
74
|
+
onChange={setOpenTime}
|
|
75
|
+
size="md"
|
|
76
|
+
clearable
|
|
77
|
+
onClear={() => setOpenTime(null)}
|
|
78
|
+
/>
|
|
79
|
+
<FormHelperText>Chọn giờ theo định dạng HH:mm</FormHelperText>
|
|
80
|
+
</Box>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Notes
|
|
84
|
+
|
|
85
|
+
- Giá trị trả về là `Date` object — chỉ phần `hour` và `minute` có ý nghĩa, `date` và `month` lấy từ `selectedDate` hiện tại hoặc `new Date()`
|
|
86
|
+
- Dropdown dùng virtualized scroll (`@tanstack/react-virtual`) nên render nhanh dù danh sách dài
|
|
87
|
+
- Hiển thị định dạng `HH:mm` (24 giờ)
|
|
88
|
+
- `size` là responsive prop: có thể override theo breakpoint: `size="md" sm={{ size: 'lg' }}`
|
|
89
|
+
|
|
90
|
+
## Related Components
|
|
91
|
+
|
|
92
|
+
- [DatePicker](../date-picker/README.md)
|
|
93
|
+
- [Floating](../floating/README.md)
|
|
94
|
+
- [FormLabel](../form-label/README.md)
|
|
95
|
+
- [FormHelperText](../form-helper-text/README.md)
|
|
96
|
+
|
|
97
|
+
## See Also
|
|
98
|
+
|
|
99
|
+
- [Component Source](./index.ts)
|
|
100
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
A floating tooltip component that displays contextual information when the user hovers or focuses on a trigger element. Built on top of @floating-ui/react for smart positioning with auto-flip and shift behavior.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Tooltip } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `children*` | `ReactElement<T>` | - | The trigger element that the tooltip is anchored to. Must be a single React element that accepts a ref. |
|
|
16
|
+
| `content` | `ReactNode` | - | The content to display inside the tooltip popup. |
|
|
17
|
+
| `placement` | `Placement` | `'top'` | Preferred placement of the tooltip relative to the trigger. Accepts any @floating-ui/react Placement value (e.g. `'top'`, `'bottom'`, `'left'`, `'right'` and their variants). Will auto-flip if there is not enough space. |
|
|
18
|
+
| `open` | `boolean` | - | Controlled open state of the tooltip. |
|
|
19
|
+
| `defaultOpen` | `boolean` | `false` | Initial open state for uncontrolled usage. |
|
|
20
|
+
| `onOpenChange` | `UseFloatingOptions['onOpenChange']` | - | Callback fired when the open state changes. Receives `(open, event, reason)`. |
|
|
21
|
+
| `contentWidth` | `number \| 'fit-parent'` | - | Controls the max-width of the tooltip popup. Use a number for a fixed pixel value, or `'fit-parent'` to match the trigger element's width. |
|
|
22
|
+
| `enable` | `true \| 'truncated'` | `true` | Controls when the tooltip is shown. Set to `'truncated'` to only show the tooltip when the trigger element's text is visually truncated (overflow hidden). |
|
|
23
|
+
| `handleClose` | `UseHoverProps['handleClose'] \| 'safe-polygon'` | - | Custom close handler for hover interactions. Pass `'safe-polygon'` to use the floating-ui safePolygon handler, which keeps the tooltip open when moving the mouse toward it. |
|
|
24
|
+
| `arrowProps` | `Partial<FloatingArrowProps>` | - | Props forwarded to the FloatingArrow component (the small arrow indicator pointing at the trigger). The fill color is automatically set to match the tooltip background. |
|
|
25
|
+
| `className` | `string` | - | Additional CSS class name applied to the tooltip trigger wrapper. |
|
|
26
|
+
|
|
27
|
+
*Required props
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### Basic tooltip
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<Tooltip content="This is a tooltip">
|
|
35
|
+
<button>Hover me</button>
|
|
36
|
+
</Tooltip>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Controlled tooltip with placement
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
const [open, setOpen] = useState(false);
|
|
43
|
+
|
|
44
|
+
<Tooltip
|
|
45
|
+
content="Details about this item"
|
|
46
|
+
placement="bottom"
|
|
47
|
+
open={open}
|
|
48
|
+
onOpenChange={setOpen}
|
|
49
|
+
>
|
|
50
|
+
<span>More info</span>
|
|
51
|
+
</Tooltip>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Truncated-only tooltip
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// Tooltip chỉ hiện khi text bị cắt ngắn (overflow ellipsis)
|
|
58
|
+
<Tooltip
|
|
59
|
+
content={fullLabelText}
|
|
60
|
+
enable="truncated"
|
|
61
|
+
contentWidth="fit-parent"
|
|
62
|
+
>
|
|
63
|
+
<p style={{ width: 120, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
|
64
|
+
{fullLabelText}
|
|
65
|
+
</p>
|
|
66
|
+
</Tooltip>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Tooltip với arrow và safe polygon
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
// Dùng safe-polygon để tooltip không đóng khi di chuột từ trigger sang tooltip
|
|
73
|
+
<Tooltip
|
|
74
|
+
content="Thông tin chi tiết"
|
|
75
|
+
placement="right"
|
|
76
|
+
handleClose="safe-polygon"
|
|
77
|
+
arrowProps={{ width: 10, height: 6 }}
|
|
78
|
+
>
|
|
79
|
+
<button>Chi tiết</button>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Tooltip với độ rộng cố định
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<Tooltip content="Nội dung dài hơn cần giới hạn chiều rộng" contentWidth={200}>
|
|
87
|
+
<span>Hover để xem</span>
|
|
88
|
+
</Tooltip>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Related Components
|
|
92
|
+
|
|
93
|
+
- [Primitive](../primitive/README.md)
|
|
94
|
+
- [FloatingArrow](../floatingarrow/README.md)
|
|
95
|
+
- [FloatingPortal](../floatingportal/README.md)
|
|
96
|
+
|
|
97
|
+
## Dependencies
|
|
98
|
+
|
|
99
|
+
- @floating-ui/react
|
|
100
|
+
- lodash-es
|
|
101
|
+
|
|
102
|
+
## See Also
|
|
103
|
+
|
|
104
|
+
- [Component Source](./index.ts)
|
|
105
|
+
- [Storybook Stories](./tooltip.stories.tsx)
|
|
106
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# UnorderedList
|
|
2
|
+
|
|
3
|
+
A polymorphic unordered list container that renders a styled `<ul>` element using the Primitive base component. It lays out its children (`ListItem`) in a vertical flex column, and is typically paired with the `ListItem` component for building structured lists with optional responsive styling via the `sx` prop.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { UnorderedList } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | `{ alignItems: 'flex-start' }` | Responsive style overrides using Emotion CSS object. Supports breakpoint keys (`sm`, `md`, `lg`) for responsive values. Merged on top of the default inline-flex column layout. |
|
|
16
|
+
| `as` | `HTMLElementType` | `"ul"` | Polymorphic tag override inherited from Primitive. Defaults to `ul`. |
|
|
17
|
+
| `children` | `React.ReactNode` | - | List content, typically one or more `ListItem` components. |
|
|
18
|
+
| `className` | `string` | - | Additional CSS class names to apply to the root element. |
|
|
19
|
+
| `...rest` | `JSX.IntrinsicElements['ul']` | - | All standard HTML `<ul>` attributes are forwarded to the root element (e.g., `id`, `aria-label`, `onClick`, etc.). |
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
### Default list
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<UnorderedList>
|
|
27
|
+
<ListItem>Item 1</ListItem>
|
|
28
|
+
<ListItem>Item 2</ListItem>
|
|
29
|
+
<ListItem>Item 3</ListItem>
|
|
30
|
+
</UnorderedList>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### List with border via sx prop
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<UnorderedList
|
|
37
|
+
sx={{
|
|
38
|
+
borderStyle: 'solid',
|
|
39
|
+
borderColor: '#ccc',
|
|
40
|
+
borderTopWidth: 1,
|
|
41
|
+
borderBottomWidth: 1,
|
|
42
|
+
borderLeftWidth: 1,
|
|
43
|
+
borderRightWidth: 1,
|
|
44
|
+
borderTopLeftRadius: 8,
|
|
45
|
+
borderTopRightRadius: 8,
|
|
46
|
+
borderBottomLeftRadius: 8,
|
|
47
|
+
borderBottomRightRadius: 8,
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
<ListItem>Item 1</ListItem>
|
|
51
|
+
<ListItem>Item 2</ListItem>
|
|
52
|
+
<ListItem>Item 3</ListItem>
|
|
53
|
+
</UnorderedList>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Responsive layout override
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<UnorderedList
|
|
60
|
+
sx={{
|
|
61
|
+
gap: 8,
|
|
62
|
+
sm: { flexDirection: 'row', flexWrap: 'wrap' },
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<ListItem>First</ListItem>
|
|
66
|
+
<ListItem>Second</ListItem>
|
|
67
|
+
<ListItem>Third</ListItem>
|
|
68
|
+
</UnorderedList>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Related Components
|
|
72
|
+
|
|
73
|
+
- [ListItem](../list-item/README.md)
|
|
74
|
+
- [Primitive](../primitive/README.md)
|
|
75
|
+
|
|
76
|
+
## Dependencies
|
|
77
|
+
|
|
78
|
+
- `lodash-es`
|
|
79
|
+
- `@emotion/react`
|
|
80
|
+
|
|
81
|
+
## See Also
|
|
82
|
+
|
|
83
|
+
- [Component Source](./index.ts)
|
|
84
|
+
- [Storybook Stories](./unordered-list.stories.tsx)
|
|
85
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Video
|
|
2
|
+
|
|
3
|
+
A wrapper around `react-player` that supports playback of YouTube, Vimeo, Twitch, TikTok, HLS, Dash, and plain HTML5 video URLs. It extends all ReactPlayer props with the project's `sx` responsive styling prop.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Video } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `src` | `string` | - | URL of the video to play. Supports YouTube, Vimeo, Twitch, TikTok, HLS/Dash streams, and direct video file URLs. |
|
|
16
|
+
| `controls` | `boolean` | true | Whether to show native player controls. |
|
|
17
|
+
| `playing` | `boolean` | false | Set to true to start or resume playback, false to pause. |
|
|
18
|
+
| `muted` | `boolean` | false | Mutes the player. Required to be true for autoplay in most browsers. |
|
|
19
|
+
| `width` | `number \| string` | - | Width of the player. Passed directly to the underlying ReactPlayer. |
|
|
20
|
+
| `height` | `number \| string` | - | Height of the player. Passed directly to the underlying ReactPlayer. |
|
|
21
|
+
| `light` | `boolean \| string \| React.ReactElement` | - | When set, renders a lightweight preview thumbnail instead of the full player. Pass true to use the video's default thumbnail, or a URL/element for a custom preview image. |
|
|
22
|
+
| `pip` | `boolean` | - | Enables Picture-in-Picture mode. |
|
|
23
|
+
| `playbackRate` | `number` | - | Sets the playback rate (e.g. 0.5, 1, 1.5, 2). |
|
|
24
|
+
| `volume` | `number` | - | Volume level between 0 and 1. |
|
|
25
|
+
| `poster` | `string` | - | URL for the poster image shown before the video plays (HTML5 video only). |
|
|
26
|
+
| `playsInline` | `boolean` | - | Plays the video inline on mobile devices rather than full screen. |
|
|
27
|
+
| `loop` | `boolean` | - | Whether to loop the video. |
|
|
28
|
+
| `playIcon` | `React.ReactNode` | - | Custom play icon element shown over the preview thumbnail. |
|
|
29
|
+
| `wrapper` | `string \| React.ComponentType<React.HTMLAttributes<HTMLDivElement>>` | - | Custom wrapper element or component for the player container. |
|
|
30
|
+
| `config` | `Config` | - | Player-specific configuration for providers such as youtube, vimeo, twitch, hls, dash, tiktok, spotify, etc. |
|
|
31
|
+
| `onReady` | `() => void` | - | Callback fired when the player is ready. |
|
|
32
|
+
| `onStart` | `(event: SyntheticEvent<HTMLVideoElement>) => void` | - | Callback fired when playback starts. |
|
|
33
|
+
| `onClickPreview` | `(event: React.SyntheticEvent) => void` | - | Callback fired when the user clicks the preview thumbnail. |
|
|
34
|
+
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Responsive Emotion CSS overrides applied to the player wrapper element. |
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
|
|
38
|
+
### Basic YouTube embed
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<Video
|
|
42
|
+
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
43
|
+
width={640}
|
|
44
|
+
height={360}
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Autoplay muted video
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<Video
|
|
52
|
+
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
|
53
|
+
width={640}
|
|
54
|
+
height={360}
|
|
55
|
+
playing
|
|
56
|
+
muted
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Lightweight preview with custom thumbnail
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<Video
|
|
64
|
+
src="https://vimeo.com/123456789"
|
|
65
|
+
width={800}
|
|
66
|
+
height={450}
|
|
67
|
+
light="https://example.com/thumbnail.jpg"
|
|
68
|
+
controls
|
|
69
|
+
config={{
|
|
70
|
+
vimeo: { byline: false, portrait: false }
|
|
71
|
+
}}
|
|
72
|
+
/>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Related Components
|
|
76
|
+
|
|
77
|
+
- [Icon](../icon/README.md)
|
|
78
|
+
- [Primitive](../primitive/README.md)
|
|
79
|
+
|
|
80
|
+
## Dependencies
|
|
81
|
+
|
|
82
|
+
- react-player
|
|
83
|
+
|
|
84
|
+
## See Also
|
|
85
|
+
|
|
86
|
+
- [Component Source](./index.ts)
|
|
87
|
+
- [Storybook Stories](./video.stories.tsx)
|
|
88
|
+
- [Main README](../../README.md)
|