@basic-ui/material 1.0.0-alpha.16 → 1.0.0-alpha.17

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.
Files changed (114) hide show
  1. package/build/cjs/index.js +294 -51
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/Alert/Alert.d.ts +1 -1
  4. package/build/esm/AppBar/AppBarButton.d.ts +1 -1
  5. package/build/esm/BottomSheet/BottomSheet.d.ts +1 -1
  6. package/build/esm/BottomSheet/BottomSheetSurface.d.ts +1 -1
  7. package/build/esm/Button/Button.d.ts +1 -1
  8. package/build/esm/Button/ButtonGroup.d.ts +1 -1
  9. package/build/esm/Button/FilledButton.d.ts +1 -1
  10. package/build/esm/Button/OutlinedButton.d.ts +1 -1
  11. package/build/esm/Button/TransparentButton.d.ts +1 -1
  12. package/build/esm/CheckBox/CheckBox.d.ts +1 -1
  13. package/build/esm/Chip/ButtonChip.d.ts +1 -1
  14. package/build/esm/Chip/ChipBase.d.ts +1 -1
  15. package/build/esm/Chip/ChoiceChip.d.ts +1 -1
  16. package/build/esm/Combobox/Combobox.d.ts +7 -7
  17. package/build/esm/Combobox/Combobox.js +4 -3
  18. package/build/esm/Combobox/Combobox.js.map +1 -1
  19. package/build/esm/Dialog/Dialog.d.ts +1 -1
  20. package/build/esm/Dialog/DialogBackdrop.d.ts +1 -1
  21. package/build/esm/Dialog/DialogSurface.d.ts +1 -1
  22. package/build/esm/Dialog/Scrim.d.ts +1 -1
  23. package/build/esm/Divider/Divider.d.ts +1 -1
  24. package/build/esm/Link/Link.d.ts +1 -1
  25. package/build/esm/Link/Link.js +12 -0
  26. package/build/esm/Link/Link.js.map +1 -1
  27. package/build/esm/ListItem/ListItem.d.ts +3 -1
  28. package/build/esm/ListItem/ListItem.js +46 -42
  29. package/build/esm/ListItem/ListItem.js.map +1 -1
  30. package/build/esm/Menu/Menu.d.ts +4 -4
  31. package/build/esm/NavRail/NavRailItem.d.ts +3 -3
  32. package/build/esm/Paper/Paper.d.ts +1 -1
  33. package/build/esm/RadioButton/RadioGroup.d.ts +1 -1
  34. package/build/esm/Ripple/useRippleSurface.d.ts +1 -0
  35. package/build/esm/Ripple/useRippleSurface.js +17 -16
  36. package/build/esm/Ripple/useRippleSurface.js.map +1 -1
  37. package/build/esm/Select/Select.d.ts +1 -1
  38. package/build/esm/Select/Select.js +4 -0
  39. package/build/esm/Select/Select.js.map +1 -1
  40. package/build/esm/Select/SelectIcon.d.ts +1 -1
  41. package/build/esm/SelectItem/SelectItem.d.ts +5 -2
  42. package/build/esm/SelectItem/SelectItem.js +17 -4
  43. package/build/esm/SelectItem/SelectItem.js.map +1 -1
  44. package/build/esm/SelectionControl/SelectionControlText.d.ts +1 -1
  45. package/build/esm/Skeleton/Skeleton.d.ts +1 -1
  46. package/build/esm/Slider/Slider.d.ts +17 -0
  47. package/build/esm/Slider/Slider.js +224 -0
  48. package/build/esm/Slider/Slider.js.map +1 -0
  49. package/build/esm/Slider/index.d.ts +1 -0
  50. package/build/esm/Slider/index.js +2 -0
  51. package/build/esm/Slider/index.js.map +1 -0
  52. package/build/esm/Snackbar/Snackbar.d.ts +1 -1
  53. package/build/esm/Switch/Switch.d.ts +1 -1
  54. package/build/esm/Tab/Tab.d.ts +1 -1
  55. package/build/esm/Tab/TabList.d.ts +1 -1
  56. package/build/esm/Tab/TabPanel.d.ts +1 -1
  57. package/build/esm/TabIndicator/TabIndicator.d.ts +1 -1
  58. package/build/esm/Table/TableHead.d.ts +1 -1
  59. package/build/esm/Table/TableRow.d.ts +1 -1
  60. package/build/esm/TextField/FilledContainer.d.ts +1 -1
  61. package/build/esm/TextField/HelperText.d.ts +1 -1
  62. package/build/esm/TextField/Input.d.ts +1 -1
  63. package/build/esm/TextField/OutlinedContainer.d.ts +1 -1
  64. package/build/esm/TextField/OutlinedContainer.js +13 -5
  65. package/build/esm/TextField/OutlinedContainer.js.map +1 -1
  66. package/build/esm/TextField/TextField.d.ts +1 -1
  67. package/build/esm/ThemeExplorer/BorderSlider.d.ts +7 -0
  68. package/build/esm/ThemeExplorer/BorderSlider.js +78 -0
  69. package/build/esm/ThemeExplorer/BorderSlider.js.map +1 -0
  70. package/build/esm/ThemeExplorer/ColorSchemePicker.d.ts +10 -0
  71. package/build/esm/ThemeExplorer/ColorSchemePicker.js +54 -0
  72. package/build/esm/ThemeExplorer/ColorSchemePicker.js.map +1 -0
  73. package/build/esm/ThemeExplorer/FontAutoComplete.d.ts +9 -0
  74. package/build/esm/ThemeExplorer/FontAutoComplete.js +128 -0
  75. package/build/esm/ThemeExplorer/FontAutoComplete.js.map +1 -0
  76. package/build/esm/ThemeExplorer/ThemeBuilder.d.ts +2 -0
  77. package/build/esm/ThemeExplorer/ThemeBuilder.js +231 -93
  78. package/build/esm/ThemeExplorer/ThemeBuilder.js.map +1 -1
  79. package/build/esm/ThemeExplorer/components.js +4 -4
  80. package/build/esm/ThemeExplorer/components.js.map +1 -1
  81. package/build/esm/ThemeExplorer/googleFonts.d.ts +1 -0
  82. package/build/esm/ThemeExplorer/googleFonts.js +7 -0
  83. package/build/esm/ThemeExplorer/googleFonts.js.map +1 -0
  84. package/build/esm/ThemeExplorer/updateGoogleFonts.js +70 -0
  85. package/build/esm/ThemeExplorer/updateGoogleFonts.js.map +1 -0
  86. package/build/esm/ThemeExplorer/useDeferredColor.js +3 -4
  87. package/build/esm/ThemeExplorer/useDeferredColor.js.map +1 -1
  88. package/build/esm/Tooltip/Tooltip.d.ts +1 -1
  89. package/build/esm/index.d.ts +1 -0
  90. package/build/esm/index.js +1 -0
  91. package/build/esm/index.js.map +1 -1
  92. package/build/tsconfig-build.tsbuildinfo +1 -1
  93. package/package.json +6 -6
  94. package/src/Combobox/Combobox.tsx +5 -2
  95. package/src/Link/Link.tsx +12 -0
  96. package/src/ListItem/ListItem.tsx +48 -41
  97. package/src/Ripple/useRippleSurface.ts +8 -2
  98. package/src/Select/PaymentMethodSelect.story.tsx +17 -24
  99. package/src/Select/Select.tsx +6 -0
  100. package/src/SelectItem/SelectItem.tsx +13 -3
  101. package/src/Slider/Slider.story.tsx +36 -0
  102. package/src/Slider/Slider.tsx +275 -0
  103. package/src/Slider/index.ts +1 -0
  104. package/src/TextField/OutlinedContainer.tsx +8 -3
  105. package/src/ThemeExplorer/BorderSlider.tsx +73 -0
  106. package/src/ThemeExplorer/ColorSchemePicker.tsx +55 -0
  107. package/src/ThemeExplorer/FontAutoComplete.tsx +139 -0
  108. package/src/ThemeExplorer/ThemeBuilder.story.tsx +2 -1
  109. package/src/ThemeExplorer/ThemeBuilder.tsx +218 -82
  110. package/src/ThemeExplorer/components.tsx +4 -4
  111. package/src/ThemeExplorer/googleFonts.ts +1436 -0
  112. package/src/ThemeExplorer/updateGoogleFonts.js +33 -0
  113. package/src/ThemeExplorer/useDeferredColor.tsx +3 -6
  114. package/src/index.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basic-ui/material",
3
- "version": "1.0.0-alpha.16",
3
+ "version": "1.0.0-alpha.17",
4
4
  "description": "Accessible React Components used as building blocks for UI patterns",
5
5
  "author": "Lucas Terra <lucasterra7@gmail.com>",
6
6
  "license": "MIT",
@@ -27,8 +27,8 @@
27
27
  "test": "echo \"Error: no test specified\" && exit 1"
28
28
  },
29
29
  "dependencies": {
30
- "@basic-ui/core": "^0.0.44",
31
- "@basic-ui/dynamic-theme": "^0.0.6",
30
+ "@basic-ui/core": "^0.0.45",
31
+ "@basic-ui/dynamic-theme": "^0.0.7",
32
32
  "@styled-system/should-forward-prop": "5.1.5",
33
33
  "@types/styled-system": "^5.1.10",
34
34
  "@types/styled-system__css": "^5.0.14",
@@ -36,11 +36,11 @@
36
36
  "styled-system": "^5.1.5"
37
37
  },
38
38
  "devDependencies": {
39
- "@basic-ui/color-picker": "^0.0.10",
39
+ "@basic-ui/color-picker": "^0.0.11",
40
40
  "@emotion/react": "11.9.0",
41
41
  "@emotion/styled": "11.8.1",
42
42
  "@material/material-color-utilities": "0.1.1",
43
- "polished": "^4.1.1"
43
+ "polished": "^4.2.2"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@babel/runtime": "^7.0.0",
@@ -52,5 +52,5 @@
52
52
  "react": "^16.14.0 || ^17.0.0 || ^18.0.0",
53
53
  "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0"
54
54
  },
55
- "gitHead": "b30b54db7352570fd1077c7c5360e8264a799792"
55
+ "gitHead": "02f6a7c4ec2599cec8a87e0d0dd4680a5dea81c2"
56
56
  }
@@ -30,7 +30,7 @@ import { TextField } from '../TextField';
30
30
  import type { ListProps } from '../List';
31
31
  import { List } from '../List';
32
32
  import type { ListItemProps } from '../ListItem';
33
- import { ListItem } from '../ListItem';
33
+ import { listItemStyle } from '../ListItem';
34
34
  import type { TextProps } from '../Text';
35
35
  import { Text } from '../Text';
36
36
  import type { ButtonProps } from '../Button';
@@ -120,6 +120,9 @@ export const ComboboxList = forwardRef<HTMLUListElement, ComboboxListProps>(
120
120
  '[data-popper-placement="bottom"] &': {
121
121
  transformOrigin: 'top center',
122
122
  },
123
+ '& [data-reach-combobox-option=""]': {
124
+ ...listItemStyle('primary'),
125
+ },
123
126
  ...__css,
124
127
  }}
125
128
  {...otherProps}
@@ -189,7 +192,7 @@ export const ComboboxOption = forwardRef<HTMLLIElement, ComboboxOptionProps>(
189
192
  const { as = 'li', ...otherProps } = props;
190
193
  return (
191
194
  <ComboboxOptionCore
192
- as={ListItem}
195
+ as={Box}
193
196
  ref={forwardedRef}
194
197
  innerAs={as}
195
198
  {...otherProps}
package/src/Link/Link.tsx CHANGED
@@ -33,6 +33,12 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(
33
33
  letterSpacing: 'inherit',
34
34
  color,
35
35
  textDecoration: 'underline',
36
+ background: 'none',
37
+ border: 'none',
38
+ borderRadius: 'extra-small',
39
+ 'button&': {
40
+ cursor: 'pointer',
41
+ },
36
42
  '&:hover,&:focus': {
37
43
  textDecoration: 'none',
38
44
  },
@@ -44,6 +50,12 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(
44
50
  '&:active': {
45
51
  bg: alpha(color, 0.16),
46
52
  },
53
+ '&[aria-disabled="true"],&:disabled': {
54
+ color: 'on.surface',
55
+ opacity: 0.38,
56
+ cursor: 'default',
57
+ pointerEvents: 'none',
58
+ },
47
59
  WebkitTapHighlightColor: 'transparent',
48
60
  ...__css,
49
61
  }}
@@ -1,6 +1,7 @@
1
1
  import type { ElementType, ReactNode } from 'react';
2
2
  import { forwardRef } from 'react';
3
3
  import { rem } from 'polished';
4
+ import type { SystemStyleObject } from '@styled-system/css';
4
5
 
5
6
  import type { BoxProps } from '../Box';
6
7
  import { Box } from '../Box';
@@ -17,6 +18,52 @@ export interface ListItemProps extends BoxProps {
17
18
  rippleColor?: string;
18
19
  }
19
20
 
21
+ export const listItemStyle = (
22
+ color: string,
23
+ hoverOpacity = 0.16,
24
+ focusOpacity = 0.24
25
+ ): SystemStyleObject => ({
26
+ variant: 'text.label-large',
27
+ px: 3,
28
+ py: rem(12),
29
+ transition: 'background-color 75ms linear',
30
+ backgroundColor: 'transparent',
31
+ color: alpha('on.surface', 0.87),
32
+ cursor: 'pointer',
33
+ display: 'flex',
34
+ alignItems: 'center',
35
+ textDecoration: 'none',
36
+ ':hover': {
37
+ backgroundColor: alpha('on.surface', hoverOpacity),
38
+ },
39
+ ':focus': {
40
+ outline: 'none',
41
+ backgroundColor: alpha('on.surface', focusOpacity),
42
+ },
43
+ ':active': {
44
+ backgroundColor: alpha('on.surface', focusOpacity),
45
+ },
46
+ '&[aria-selected="true"]': {
47
+ backgroundColor: alpha(color, 0.08),
48
+ color,
49
+ ':hover': {
50
+ backgroundColor: alpha(color, hoverOpacity),
51
+ },
52
+ ':focus': {
53
+ outline: 'none',
54
+ backgroundColor: alpha(color, focusOpacity),
55
+ },
56
+ ':active': {
57
+ backgroundColor: alpha(color, focusOpacity),
58
+ },
59
+ },
60
+ '&[data-disabled]': {
61
+ color: alpha('on.surface', 0.6),
62
+ backgroundColor: 'transparent',
63
+ cursor: 'default',
64
+ },
65
+ });
66
+
20
67
  export const ListItem = forwardRef<HTMLDivElement, ListItemProps>(
21
68
  function ListItem(props, forwardedRef) {
22
69
  const {
@@ -35,9 +82,6 @@ export const ListItem = forwardRef<HTMLDivElement, ListItemProps>(
35
82
  const color = rippleColor || colorProp || 'primary';
36
83
  const theme = useTheme();
37
84
 
38
- const hoverOpacity = 0.16;
39
- const focusOpacity = 0.24;
40
-
41
85
  return (
42
86
  <Box
43
87
  ref={forwardedRef}
@@ -49,44 +93,7 @@ export const ListItem = forwardRef<HTMLDivElement, ListItemProps>(
49
93
  disabled={disabled}
50
94
  {...otherProps}
51
95
  __css={{
52
- variant: 'text.label-large',
53
- px: 3,
54
- py: rem(12),
55
- transition: 'background-color 75ms linear',
56
- backgroundColor: 'transparent',
57
- color: alpha('on.surface', 0.87),
58
- cursor: 'pointer',
59
- ':hover': {
60
- backgroundColor: alpha('on.surface', hoverOpacity),
61
- },
62
- ':focus': {
63
- outline: 'none',
64
- backgroundColor: alpha('on.surface', focusOpacity),
65
- },
66
- ':active': {
67
- backgroundColor: alpha('on.surface', focusOpacity),
68
- },
69
- '&[aria-selected="true"]': {
70
- backgroundColor: alpha(color, 0.08),
71
- color,
72
- ':hover': {
73
- backgroundColor: alpha(color, hoverOpacity),
74
- },
75
- ':focus': {
76
- outline: 'none',
77
- backgroundColor: alpha(color, focusOpacity),
78
- },
79
- ':active': {
80
- backgroundColor: alpha(color, focusOpacity),
81
- },
82
- },
83
- '&[data-disabled]': {
84
- color: alpha('on.surface', 0.6),
85
- backgroundColor: 'transparent',
86
- cursor: 'default',
87
- },
88
- textDecoration: 'none',
89
- WebkitTapHighlightColor: 'transparent',
96
+ ...listItemStyle(color),
90
97
  ...__css,
91
98
  }}
92
99
  >
@@ -20,6 +20,7 @@ export interface UseRippleSurfaceOptions<T extends HTMLElement> {
20
20
  rippleColor?: string;
21
21
  rippleEnabled?: boolean;
22
22
  center?: boolean;
23
+ mouseFocus?: boolean;
23
24
  disabled?: boolean;
24
25
  style?: CSSProperties;
25
26
  onPointerDown?: PointerEventHandler<T>;
@@ -36,6 +37,8 @@ export function useRippleSurface<T extends HTMLElement>(
36
37
  focusOpacity = 0.12,
37
38
  pressedOpacity = 0.12,
38
39
  rippleColor = 'on.surface',
40
+ // eslint-disable-next-line prefer-const
41
+ mouseFocus = false,
39
42
  } = opts;
40
43
  const {
41
44
  onKeyDown,
@@ -67,6 +70,8 @@ export function useRippleSurface<T extends HTMLElement>(
67
70
  ...rippleProps,
68
71
  });
69
72
 
73
+ const focusPseudoClass = mouseFocus ? 'focus' : 'focus-visible';
74
+
70
75
  const css: SxStyleProp = useMemo(
71
76
  () => ({
72
77
  overflow: 'hidden',
@@ -93,7 +98,7 @@ export function useRippleSurface<T extends HTMLElement>(
93
98
  '&:hover::before': {
94
99
  opacity: hoverOpacity,
95
100
  },
96
- '&:focus-visible::before': {
101
+ [`&:${focusPseudoClass}::before`]: {
97
102
  opacity: focusOpacity,
98
103
  },
99
104
  ...(!rippleEnabled && {
@@ -107,7 +112,7 @@ export function useRippleSurface<T extends HTMLElement>(
107
112
  '&[aria-pressed="true"]:hover::before': {
108
113
  opacity: pressedOpacity + hoverOpacity,
109
114
  },
110
- '&[aria-pressed="true"]:focus-visible::before': {
115
+ [`&[aria-pressed="true"]:${focusPseudoClass}::before`]: {
111
116
  opacity: pressedOpacity + focusOpacity,
112
117
  },
113
118
  ...(!rippleEnabled && {
@@ -133,6 +138,7 @@ export function useRippleSurface<T extends HTMLElement>(
133
138
  animation,
134
139
  baseOpacity,
135
140
  focusOpacity,
141
+ focusPseudoClass,
136
142
  hoverOpacity,
137
143
  pressedOpacity,
138
144
  rippleColor,
@@ -1,8 +1,9 @@
1
1
  import { forwardRef, useState } from 'react';
2
2
  import type { ReactElement, ComponentType } from 'react';
3
+ import styled from '@emotion/styled';
3
4
 
4
5
  import type { SelectProps } from '../';
5
- import { Box, Select, SelectItem } from '../';
6
+ import { Select, SelectItem } from '../';
6
7
 
7
8
  export default {
8
9
  title: 'components/Select/Complex',
@@ -176,25 +177,19 @@ export interface PaymentMethodSelectProps {
176
177
 
177
178
  const logoWidth = 32;
178
179
  const logoHeight = 24;
179
- const LogoWrapper = ({ children }: { children: ReactElement }) => (
180
- <Box
181
- sx={{
182
- mr: 2,
183
- borderRadius: '2px',
184
- overflow: 'hidden',
185
- width: logoWidth,
186
- height: logoHeight,
187
- minWidth: logoWidth,
188
- minHeight: logoHeight,
189
- '& > svg': { width: logoWidth, height: logoWidth },
190
- display: 'inline-flex',
191
- alignItems: 'center',
192
- justifyContent: 'center',
193
- }}
194
- >
195
- {children}
196
- </Box>
197
- );
180
+ const LogoWrapper = styled.div({
181
+ marginInlineEnd: '8px',
182
+ borderRadius: '2px',
183
+ overflow: 'hidden',
184
+ width: logoWidth,
185
+ height: logoHeight,
186
+ minWidth: logoWidth,
187
+ minHeight: logoHeight,
188
+ '& > svg': { width: logoWidth, height: logoWidth },
189
+ display: 'inline-flex',
190
+ alignItems: 'center',
191
+ justifyContent: 'center',
192
+ });
198
193
 
199
194
  function SelectItemContent(props: PaymentMethod): ReactElement {
200
195
  if (props.type === 'card') {
@@ -269,9 +264,7 @@ const PaymentMethodSelect = forwardRef<
269
264
  >
270
265
  {paymentMethods.map((m) => (
271
266
  <SelectItem value={m.id} key={m.id}>
272
- <Box display="inline-flex" alignItems="center">
273
- <SelectItemContent {...m} />
274
- </Box>
267
+ <SelectItemContent {...m} />
275
268
  </SelectItem>
276
269
  ))}
277
270
  </Select>
@@ -300,7 +293,7 @@ export const PaymentMethodSelectControlled = () => {
300
293
  'visa',
301
294
  'unknown',
302
295
  ]) {
303
- for (let i = 0; i < 10; i++) {
296
+ for (let i = 0; i < 50; i++) {
304
297
  paymentMethods.push({
305
298
  type: 'card',
306
299
  id: testCard + `_${i}`,
@@ -24,6 +24,7 @@ import { makeDefaultRender } from './defaultRender';
24
24
  import type { BoxProps } from '../Box';
25
25
  import { Box } from '../Box';
26
26
  import { IconContainer } from '../TextField/IconContainer';
27
+ import { listItemStyle } from '../ListItem';
27
28
 
28
29
  const componentMap = {
29
30
  outlined: OutlinedContainer,
@@ -181,6 +182,11 @@ export const Select = forwardRef<
181
182
  minWidth: buttonRef?.current?.offsetWidth,
182
183
  }}
183
184
  role="listbox"
185
+ __css={{
186
+ '& [data-menu-item=""]': {
187
+ ...listItemStyle('primary'),
188
+ },
189
+ }}
184
190
  >
185
191
  {children}
186
192
  </MenuList>
@@ -1,9 +1,18 @@
1
1
  import { forwardRef } from 'react';
2
- import { wrapEvent } from '@basic-ui/core';
2
+ import { wrapEvent, MenuItem as MenuItemCore } from '@basic-ui/core';
3
+ import type { MenuItemProps as MenuItemPropsCore } from '@basic-ui/core';
3
4
 
4
- import type { MenuItemProps } from '../Menu';
5
- import { MenuItem } from '../Menu';
6
5
  import { useSelectContext } from '../Select/context';
6
+ import type { BoxProps } from '../Box';
7
+ import { Box } from '../Box';
8
+
9
+ type MenuItemProps = MenuItemPropsCore & BoxProps;
10
+
11
+ const MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(
12
+ ({ as = 'li', ...props }, ref) => (
13
+ <MenuItemCore as={Box} innerAs={as} ref={ref} {...props} />
14
+ )
15
+ );
7
16
 
8
17
  export type SelectItemProps = MenuItemProps;
9
18
 
@@ -50,6 +59,7 @@ export const SelectItem = forwardRef<HTMLLIElement, MenuItemProps>(
50
59
  disabled={disabled}
51
60
  ref={forwardedRef}
52
61
  role="option"
62
+ aria-selected={selected ? 'true' : undefined}
53
63
  selected={selected}
54
64
  {...otherProps}
55
65
  >
@@ -0,0 +1,36 @@
1
+ import { Slider, SliderMarker } from './';
2
+ // import './styles.css';
3
+
4
+ export default { title: 'components/Slider' };
5
+
6
+ export const Uncontrolled = () => <Slider />;
7
+
8
+ export const UncontrolledWithSteps = () => <Slider step={10} />;
9
+
10
+ export const UncontrolledWithMarks = () => (
11
+ <Slider>
12
+ <SliderMarker value={10} />
13
+ <SliderMarker value={20} />
14
+ <SliderMarker value={30} />
15
+ <SliderMarker value={40} />
16
+ <SliderMarker value={50} />
17
+ <SliderMarker value={60} />
18
+ <SliderMarker value={70} />
19
+ <SliderMarker value={80} />
20
+ <SliderMarker value={90} />
21
+ </Slider>
22
+ );
23
+
24
+ export const UncontrolledWithMarksAndSteps = () => (
25
+ <Slider step={10}>
26
+ <SliderMarker value={10} />
27
+ <SliderMarker value={20} />
28
+ <SliderMarker value={30} />
29
+ <SliderMarker value={40} />
30
+ <SliderMarker value={50} />
31
+ <SliderMarker value={60} />
32
+ <SliderMarker value={70} />
33
+ <SliderMarker value={80} />
34
+ <SliderMarker value={90} />
35
+ </Slider>
36
+ );
@@ -0,0 +1,275 @@
1
+ import {
2
+ SliderHandle as SliderHandleCore,
3
+ SliderInput as SliderInputCore,
4
+ SliderMarker as SliderMarkerCore,
5
+ SliderTrack as SliderTrackCore,
6
+ SliderRange as SliderRangeCore,
7
+ } from '@basic-ui/core';
8
+ import type {
9
+ SliderProps as SliderPropsCore,
10
+ SliderHandleProps as SliderHandlePropsCore,
11
+ SliderInputProps as SliderInputPropsCore,
12
+ SliderMarkerProps as SliderMarkerPropsCore,
13
+ SliderTrackProps as SliderTrackPropsCore,
14
+ SliderRangeProps as SliderRangePropsCore,
15
+ } from '@basic-ui/core';
16
+ export type { SliderHandleAlignment } from '@basic-ui/core';
17
+ import type { HTMLAttributes } from 'react';
18
+ import { forwardRef } from 'react';
19
+ import { rem } from 'polished';
20
+
21
+ import type { BoxProps } from '../Box';
22
+ import { Box } from '../Box';
23
+ import { alpha } from '../color';
24
+ import type { RippleBoxProps } from '../Ripple';
25
+ import { RippleBox } from '../Ripple';
26
+
27
+ /////////////////////////////////////////////////////
28
+ // SliderInput
29
+
30
+ export type SliderInputProps = Omit<
31
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>,
32
+ | 'onChange'
33
+ | 'onMouseDown'
34
+ | 'onMouseMove'
35
+ | 'onMouseUp'
36
+ | 'onPointerDown'
37
+ | 'onPointerUp'
38
+ | 'onTouchEnd'
39
+ | 'onTouchMove'
40
+ | 'onTouchStart'
41
+ > &
42
+ SliderInputPropsCore;
43
+
44
+ export const SliderInput = forwardRef<HTMLDivElement, SliderInputProps>(
45
+ ({ as = 'div', __css, ...props }, ref) => (
46
+ <SliderInputCore
47
+ as={Box}
48
+ innerAs={as as any}
49
+ ref={ref}
50
+ {...props}
51
+ __css={{
52
+ maxWidth: '100%',
53
+ cursor: 'pointer',
54
+ '&[data-orientation="horizontal"]': { height: rem(4) },
55
+ '&[data-orientation="vertical"]': {
56
+ width: rem(4),
57
+ height: '250px',
58
+ maxHeight: '100%',
59
+ },
60
+ '&[data-disabled]': { opacity: 0.5, pointerEvents: 'none' },
61
+ ...__css,
62
+ }}
63
+ />
64
+ )
65
+ );
66
+
67
+ /////////////////////////////////////////////////////
68
+ // SliderHandle
69
+
70
+ export type SliderHandleProps = SliderHandlePropsCore &
71
+ RippleBoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
72
+
73
+ export const SliderHandle = forwardRef<HTMLDivElement, SliderHandleProps>(
74
+ ({ as = 'div', __css, children, ...props }, ref) => (
75
+ <SliderHandleCore
76
+ as={RippleBox}
77
+ innerAs={as as any}
78
+ ref={ref}
79
+ rippleColor="currentColor"
80
+ hoverOpacity={0.12}
81
+ focusOpacity={0.24}
82
+ pressedOpacity={0.24}
83
+ mouseFocus
84
+ center
85
+ __css={{
86
+ position: 'relative',
87
+ width: rem(40),
88
+ height: rem(40),
89
+ color: 'primary',
90
+ borderRadius: 'full',
91
+ zIndex: 1,
92
+ transformOrigin: 'center',
93
+ userSelect: 'none',
94
+ '&[aria-orientation="horizontal"]': {
95
+ top: '50%',
96
+ transform: 'translateY(-50%)',
97
+ },
98
+ '&[aria-orientation="horizontal"]:focus': {
99
+ transform: 'translateY(-50%)',
100
+ },
101
+ '&[aria-orientation="vertical"]': {
102
+ left: '50%',
103
+ transform: 'translateX(-50%)',
104
+ },
105
+ ':focus': {
106
+ outline: 'none',
107
+ },
108
+ ...__css,
109
+ }}
110
+ {...props}
111
+ >
112
+ <Box
113
+ __css={{
114
+ bg: 'currentColor',
115
+ width: '50%',
116
+ height: '50%',
117
+ borderRadius: 'full',
118
+ pointerEvents: 'none',
119
+ position: 'absolute',
120
+ top: '50%',
121
+ left: '50%',
122
+ transform: 'translate(-50%, -50%)',
123
+ boxShadow: 1,
124
+ }}
125
+ />
126
+ {children}
127
+ </SliderHandleCore>
128
+ )
129
+ );
130
+
131
+ /////////////////////////////////////////////////////
132
+ // SliderMarker
133
+
134
+ export type SliderMarkerProps = SliderMarkerPropsCore &
135
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
136
+
137
+ export const SliderMarker = forwardRef<HTMLDivElement, SliderMarkerProps>(
138
+ ({ as = 'div', __css, ...props }, ref) => (
139
+ <SliderMarkerCore
140
+ as={Box}
141
+ innerAs={as as any}
142
+ ref={ref}
143
+ {...props}
144
+ __css={{
145
+ transformOrigin: 'center',
146
+ borderRadius: 'full',
147
+ width: '2px',
148
+ height: '2px',
149
+ '&[data-orientation="horizontal"]': {
150
+ top: '50%',
151
+ transform: 'translate(-50%, -50%)',
152
+ },
153
+ '&[data-orientation="vertical"]': {
154
+ left: '50%',
155
+ transform: 'translate(-50%, -50%)',
156
+ },
157
+ bg: alpha('primary', 0.8),
158
+ '&[data-state="at-value"],&[data-state="under-value"]': {
159
+ bg: alpha('on.primary', 0.8),
160
+ },
161
+ ...__css,
162
+ }}
163
+ />
164
+ )
165
+ );
166
+
167
+ /////////////////////////////////////////////////////
168
+ // SliderTrack
169
+
170
+ export type SliderTrackProps = SliderTrackPropsCore &
171
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
172
+
173
+ export const SliderTrack = forwardRef<HTMLDivElement, SliderTrackProps>(
174
+ ({ as = 'div', __css, ...props }, ref) => (
175
+ <SliderTrackCore
176
+ as={Box}
177
+ innerAs={as as any}
178
+ ref={ref}
179
+ {...props}
180
+ __css={{
181
+ position: 'relative',
182
+ borderRadius: 'full',
183
+ bg: alpha('primary', 0.38),
184
+ '&[data-orientation="horizontal"]': {
185
+ width: '100%',
186
+ height: 'inherit',
187
+ },
188
+ '&[data-orientation="vertical"]': {
189
+ width: 'inherit',
190
+ height: '100%',
191
+ },
192
+ '&::before': {
193
+ content: '""',
194
+ position: 'absolute',
195
+ },
196
+ '&[data-orientation="horizontal"]::before': {
197
+ width: '100%',
198
+ height: '1.5rem',
199
+ top: 'calc(-0.5rem - 1px)',
200
+ left: '0',
201
+ },
202
+ '&[data-orientation="vertical"]::before': {
203
+ width: '1.5rem',
204
+ height: '100%',
205
+ top: '0',
206
+ left: 'calc(-0.5rem - 1px)',
207
+ },
208
+ ...__css,
209
+ }}
210
+ />
211
+ )
212
+ );
213
+
214
+ /////////////////////////////////////////////////////
215
+ // SliderRange
216
+
217
+ export type SliderRangeProps = SliderRangePropsCore &
218
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>;
219
+
220
+ export const SliderRange = forwardRef<HTMLDivElement, SliderRangeProps>(
221
+ ({ as = 'div', __css, ...props }, ref) => (
222
+ <SliderRangeCore
223
+ as={Box}
224
+ innerAs={as as any}
225
+ ref={ref}
226
+ __css={{
227
+ borderRadius: 'inherit',
228
+ bg: 'primary',
229
+ left: '0',
230
+ bottom: '0',
231
+ top: '50%',
232
+ '&[data-orientation="horizontal"]': {
233
+ height: '150%',
234
+ },
235
+ '&[data-orientation="vertical"]': {
236
+ width: '150%',
237
+ },
238
+ transform: 'translateY(-50%)',
239
+ ...__css,
240
+ }}
241
+ {...props}
242
+ />
243
+ )
244
+ );
245
+
246
+ export type SliderProps = SliderPropsCore &
247
+ Omit<
248
+ BoxProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>>,
249
+ | 'onChange'
250
+ | 'onMouseDown'
251
+ | 'onMouseMove'
252
+ | 'onMouseUp'
253
+ | 'onPointerDown'
254
+ | 'onPointerUp'
255
+ | 'onTouchEnd'
256
+ | 'onTouchMove'
257
+ | 'onTouchStart'
258
+ >;
259
+
260
+ export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
261
+ props,
262
+ forwardedRef
263
+ ) {
264
+ const { children, ...otherProps } = props;
265
+
266
+ return (
267
+ <SliderInput {...otherProps} ref={forwardedRef} data-reach-slider="">
268
+ <SliderTrack>
269
+ <SliderRange />
270
+ <SliderHandle />
271
+ {children}
272
+ </SliderTrack>
273
+ </SliderInput>
274
+ );
275
+ });