@basic-ui/material 1.0.0-alpha.3 → 1.0.0-alpha.6

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 (44) hide show
  1. package/build/cjs/index.js +13 -13
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/AppBar/AppBarButton.d.ts +1 -1
  4. package/build/esm/Button/Button.d.ts +1 -1
  5. package/build/esm/Button/ButtonGroup.d.ts +1 -1
  6. package/build/esm/CheckBox/CheckBox.d.ts +1 -1
  7. package/build/esm/Chip/ButtonChip.d.ts +1 -1
  8. package/build/esm/Chip/ChoiceChip.d.ts +1 -1
  9. package/build/esm/Combobox/Combobox.d.ts +7 -7
  10. package/build/esm/Menu/Menu.d.ts +4 -4
  11. package/build/esm/NavRail/NavRailItem.d.ts +14 -0
  12. package/build/esm/NavRail/NavRailItem.js +131 -0
  13. package/build/esm/NavRail/NavRailItem.js.map +1 -0
  14. package/build/esm/NavRail/index.d.ts +1 -0
  15. package/build/esm/NavRail/index.js +2 -0
  16. package/build/esm/NavRail/index.js.map +1 -0
  17. package/build/esm/Ripple/useRippleSurface.d.ts +2 -2
  18. package/build/esm/Ripple/useRippleSurface.js +63 -58
  19. package/build/esm/Ripple/useRippleSurface.js.map +1 -1
  20. package/build/esm/Select/Select.d.ts +1 -1
  21. package/build/esm/SelectItem/SelectItem.d.ts +1 -1
  22. package/build/esm/Switch/Switch.d.ts +2 -3
  23. package/build/esm/Switch/Switch.js.map +1 -1
  24. package/build/esm/Tab/Tab.d.ts +1 -1
  25. package/build/esm/Tab/Tab.js +1 -1
  26. package/build/esm/Tab/Tab.js.map +1 -1
  27. package/build/esm/ThemeExplorer/components.js +2 -1
  28. package/build/esm/ThemeExplorer/components.js.map +1 -1
  29. package/build/esm/ThemeExplorer/makeColorScheme.js +2 -1
  30. package/build/esm/ThemeExplorer/makeColorScheme.js.map +1 -1
  31. package/build/esm/ThemeExplorer/useDeferredColor.js +2 -1
  32. package/build/esm/ThemeExplorer/useDeferredColor.js.map +1 -1
  33. package/build/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +3 -3
  35. package/src/NavRail/NavRail.story.tsx +109 -0
  36. package/src/NavRail/NavRailItem.tsx +158 -0
  37. package/src/NavRail/index.ts +1 -0
  38. package/src/Ripple/useRippleSurface.ts +72 -58
  39. package/src/Switch/Switch.tsx +1 -1
  40. package/src/Tab/Tab.tsx +1 -1
  41. package/src/ThemeExplorer/ThemeBuilder.story.tsx +1 -1
  42. package/src/ThemeExplorer/components.tsx +1 -1
  43. package/src/ThemeExplorer/makeColorScheme.tsx +1 -1
  44. package/src/ThemeExplorer/useDeferredColor.tsx +1 -1
@@ -0,0 +1,158 @@
1
+ import React, { forwardRef, useMemo } from 'react';
2
+ import { rem } from 'polished';
3
+ import { get } from 'styled-system';
4
+
5
+ import type { BoxProps, SxStyleProp } from '../Box';
6
+ import { Box } from '../Box';
7
+ import { useTheme } from '../theme';
8
+ import { Text } from '../Text';
9
+ import type { TextProps } from '../Text';
10
+ import type { RippleBoxProps } from '../Ripple';
11
+ import { useRippleSurface } from '../Ripple';
12
+
13
+ export interface NavRailItemProps extends Omit<BoxProps, 'color'> {
14
+ as?: React.ElementType<any>;
15
+ children?: React.ReactNode;
16
+ disabled?: boolean;
17
+ selected?: boolean;
18
+ color?: string;
19
+ }
20
+
21
+ export const NavRailIndicator = forwardRef<HTMLDivElement, RippleBoxProps>(
22
+ function NavRailIndicator(props, forwardedRef) {
23
+ const { as = 'div', children, __css, ...otherProps } = props;
24
+
25
+ return (
26
+ <Box
27
+ color="currentColor"
28
+ ref={forwardedRef}
29
+ as={as}
30
+ data-nav-rail-item-indicator=""
31
+ {...otherProps}
32
+ __css={{
33
+ width: '100%',
34
+ height: '100%',
35
+ maxWidth: rem(56),
36
+ maxHeight: rem(56),
37
+ borderRadius: 'full',
38
+ bg: 'var(--indicator-background-color)',
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ justifyContent: 'center',
42
+ minHeight: rem(32),
43
+ ...__css,
44
+ }}
45
+ >
46
+ {children}
47
+ </Box>
48
+ );
49
+ }
50
+ );
51
+
52
+ export const NavRailLabel = forwardRef<HTMLDivElement, TextProps>(
53
+ function NavRailLabel(props, forwardedRef) {
54
+ const { as = 'div', children, __css, ...otherProps } = props;
55
+
56
+ return (
57
+ <Text
58
+ ref={forwardedRef}
59
+ as={as}
60
+ variant="caption"
61
+ {...otherProps}
62
+ lineHeight={1}
63
+ __css={{
64
+ pt: rem(4),
65
+ pb: rem(12),
66
+ color: 'inherit',
67
+ ...__css,
68
+ }}
69
+ >
70
+ {children}
71
+ </Text>
72
+ );
73
+ }
74
+ );
75
+
76
+ export const NavRailItem = forwardRef<HTMLDivElement, NavRailItemProps>(
77
+ function NavRailItem(props, forwardedRef) {
78
+ const {
79
+ as = 'button',
80
+ children,
81
+ color = 'primary-container',
82
+ selected = false,
83
+ disabled = false,
84
+ style,
85
+ onKeyDown,
86
+ onPointerDown,
87
+ __css,
88
+ ...otherProps
89
+ } = props;
90
+ const theme = useTheme();
91
+ const baseOpacity = 0,
92
+ hoverOpacity = 0.04,
93
+ focusOpacity = 0.12,
94
+ pressedOpacity = 0.12;
95
+ const ripple = useRippleSurface({
96
+ rippleColor: `on.${color}`,
97
+ onKeyDown,
98
+ onPointerDown,
99
+ baseOpacity,
100
+ hoverOpacity,
101
+ focusOpacity,
102
+ pressedOpacity,
103
+ });
104
+
105
+ // Apply ripple from nav item to nav indicator
106
+ const rippleCss = useMemo(() => {
107
+ const ret: SxStyleProp = {};
108
+ const keys = Object.keys(ripple.__css);
109
+ for (const key of keys) {
110
+ const newKey =
111
+ key === '&'
112
+ ? '& [data-nav-rail-item-indicator]'
113
+ : key.replace(
114
+ /(.+?)::(before|after)/g,
115
+ '$1 [data-nav-rail-item-indicator]::$2'
116
+ );
117
+ ret[newKey] = ripple.__css[key];
118
+ }
119
+ return ret;
120
+ }, [ripple.__css]);
121
+
122
+ return (
123
+ <Box
124
+ ref={forwardedRef}
125
+ as={as}
126
+ {...otherProps}
127
+ onPointerDown={ripple.onPointerDown}
128
+ onKeyDown={ripple.onKeyDown}
129
+ aria-pressed={selected}
130
+ type="button"
131
+ style={{ ...ripple.style, ...style }}
132
+ __css={{
133
+ display: 'flex',
134
+ flexDirection: 'column',
135
+ alignItems: 'center',
136
+ color: `on.${color}`,
137
+ '--indicator-background-color': selected
138
+ ? get(theme, `colors.${color}`)
139
+ : 'transparent',
140
+ border: 'none',
141
+ ':focus': {
142
+ outline: 'none',
143
+ },
144
+ backgroundColor: 'transparent',
145
+ margin: 0,
146
+ padding: 0,
147
+ px: rem(12),
148
+ cursor: 'pointer',
149
+ textDecoration: 'none',
150
+ ...rippleCss,
151
+ ...__css,
152
+ }}
153
+ >
154
+ {children}
155
+ </Box>
156
+ );
157
+ }
158
+ );
@@ -0,0 +1 @@
1
+ export * from './NavRailItem';
@@ -1,4 +1,5 @@
1
1
  import type { CSSProperties } from 'react';
2
+ import { useMemo } from 'react';
2
3
  import { get } from '@styled-system/css';
3
4
  import { wrapEvent } from '@basic-ui/core';
4
5
 
@@ -22,7 +23,7 @@ export interface UseRippleSurfaceOptions<T extends HTMLElement> {
22
23
  }
23
24
 
24
25
  export function useRippleSurface<T extends HTMLElement>(
25
- opts: UseRippleSurfaceOptions<T>
26
+ opts: UseRippleSurfaceOptions<T> = {}
26
27
  ) {
27
28
  let {
28
29
  // eslint-disable-next-line prefer-const
@@ -62,67 +63,80 @@ export function useRippleSurface<T extends HTMLElement>(
62
63
  ...rippleProps,
63
64
  });
64
65
 
65
- const css: SxStyleProp = {
66
- overflow: 'hidden',
67
- position: 'relative',
68
- cursor: 'pointer',
69
- // fix overflow: hidden + borderRadius in Safari
70
- // https://gist.github.com/ayamflow/b602ab436ac9f05660d9c15190f4fd7b#gistcomment-2359479
71
- willChange: 'transform,opacity',
72
- WebkitTapHighlightColor: 'transparent',
73
- // ripple overlay
74
- '&::before': {
75
- backgroundColor: rippleColor,
76
- boxSizing: 'content-box',
77
- position: 'absolute',
78
- content: '""',
79
- opacity: baseOpacity,
80
- pointerEvents: 'none',
81
- top: '0',
82
- left: '0',
83
- width: '100%',
84
- height: '100%',
85
- transition: 'opacity 75ms linear',
86
- },
87
- '&:hover::before': {
88
- opacity: hoverOpacity,
89
- },
90
- '&:focus-visible::before': {
91
- opacity: focusOpacity,
92
- },
93
- ...(!rippleEnabled && {
94
- '&:active::before': {
95
- opacity: pressedOpacity,
66
+ const css: SxStyleProp = useMemo(
67
+ () => ({
68
+ '&': {
69
+ overflow: 'hidden',
70
+ position: 'relative',
71
+ cursor: 'pointer',
72
+ // fix overflow: hidden + borderRadius in Safari
73
+ // https://gist.github.com/ayamflow/b602ab436ac9f05660d9c15190f4fd7b#gistcomment-2359479
74
+ willChange: 'transform,opacity',
75
+ WebkitTapHighlightColor: 'transparent',
96
76
  },
97
- }),
98
- '&[aria-pressed="true"]::before': {
99
- opacity: baseOpacity + pressedOpacity,
100
- },
101
- '&[aria-pressed="true"]:hover::before': {
102
- opacity: pressedOpacity + hoverOpacity,
103
- },
104
- '&[aria-pressed="true"]:focus-visible::before': {
105
- opacity: pressedOpacity + focusOpacity,
106
- },
107
- ...(!rippleEnabled && {
108
- '&[aria-pressed="true"]:active::before': {
109
- opacity: pressedOpacity + pressedOpacity,
77
+ // ripple overlay
78
+ '&::before': {
79
+ backgroundColor: rippleColor,
80
+ boxSizing: 'content-box',
81
+ position: 'absolute',
82
+ content: '""',
83
+ opacity: baseOpacity,
84
+ pointerEvents: 'none',
85
+ top: '0',
86
+ left: '0',
87
+ width: '100%',
88
+ height: '100%',
89
+ transition: 'opacity 75ms linear',
110
90
  },
111
- }),
112
- ['&:disabled::before,&:disabled:hover::before,&:disabled:focus::before,&:disabled:active::before,' +
113
- '&[data-disabled]::before,&[data-disabled]:hover::before,&[data-disabled]:focus::before,' +
114
- '&[data-disabled]:active::before,&:disabled[aria-pressed="true"]::before']:
115
- {
116
- opacity: 0,
91
+ '&:hover::before': {
92
+ opacity: hoverOpacity,
93
+ },
94
+ '&:focus-visible::before': {
95
+ opacity: focusOpacity,
96
+ },
97
+ ...(!rippleEnabled && {
98
+ '&:active::before': {
99
+ opacity: pressedOpacity,
100
+ },
101
+ }),
102
+ '&[aria-pressed="true"]::before': {
103
+ opacity: baseOpacity + pressedOpacity,
117
104
  },
118
- '&:disabled,&[data-disabled]': {
119
- cursor: 'default',
120
- },
121
- // ripple
122
- ...(rippleEnabled && {
123
- '&::after': { ...rippleStyle({ animation }) },
105
+ '&[aria-pressed="true"]:hover::before': {
106
+ opacity: pressedOpacity + hoverOpacity,
107
+ },
108
+ '&[aria-pressed="true"]:focus-visible::before': {
109
+ opacity: pressedOpacity + focusOpacity,
110
+ },
111
+ ...(!rippleEnabled && {
112
+ '&[aria-pressed="true"]:active::before': {
113
+ opacity: pressedOpacity + pressedOpacity,
114
+ },
115
+ }),
116
+ ['&:disabled::before,&:disabled:hover::before,&:disabled:focus::before,&:disabled:active::before,' +
117
+ '&[data-disabled]::before,&[data-disabled]:hover::before,&[data-disabled]:focus::before,' +
118
+ '&[data-disabled]:active::before,&:disabled[aria-pressed="true"]::before']:
119
+ {
120
+ opacity: 0,
121
+ },
122
+ '&:disabled,&[data-disabled]': {
123
+ cursor: 'default',
124
+ },
125
+ // ripple
126
+ ...(rippleEnabled && {
127
+ '&::after': { ...rippleStyle({ animation }) },
128
+ }),
124
129
  }),
125
- };
130
+ [
131
+ animation,
132
+ baseOpacity,
133
+ focusOpacity,
134
+ hoverOpacity,
135
+ pressedOpacity,
136
+ rippleColor,
137
+ rippleEnabled,
138
+ ]
139
+ );
126
140
 
127
141
  return {
128
142
  style: { ...animationStyle, ...style },
@@ -20,7 +20,7 @@ const CheckBoxCore: React.FC<
20
20
  }
21
21
  > = _CheckBoxCore as any;
22
22
 
23
- interface SwitchProps
23
+ export interface SwitchProps
24
24
  extends BoxProps<
25
25
  HTMLInputElement,
26
26
  React.InputHTMLAttributes<HTMLInputElement>
package/src/Tab/Tab.tsx CHANGED
@@ -27,7 +27,7 @@ const TabInner = forwardRef<
27
27
  const { textColor, indicatorColor, selectedTextColor } = useTabListContext();
28
28
 
29
29
  return (
30
- <Box position="relative" display="flex" flexGrow={1} flexDirection="column">
30
+ <Box position="relative" display="flex" flex={1} flexDirection="column">
31
31
  <RippleBox<
32
32
  RippleBoxProps<
33
33
  HTMLButtonElement,
@@ -3,7 +3,7 @@ import {
3
3
  CorePalette,
4
4
  argbFromHex,
5
5
  hexFromArgb,
6
- } from '@material/material-color-utilities';
6
+ } from '@material/material-color-utilities'; // eslint-disable-line import/no-unresolved
7
7
  import type { Color } from '@basic-ui/color-picker';
8
8
  import { toColor } from '@basic-ui/color-picker';
9
9
 
@@ -1,7 +1,7 @@
1
1
  import type { CSSProperties } from 'react';
2
2
  import React, { memo, useState } from 'react';
3
3
  import { rgb, parseToHsl, parseToRgb } from 'polished';
4
- import { hexFromArgb, TonalPalette } from '@material/material-color-utilities';
4
+ import { hexFromArgb, TonalPalette } from '@material/material-color-utilities'; // eslint-disable-line import/no-unresolved
5
5
 
6
6
  import { Box, Text, Tooltip } from '../';
7
7
 
@@ -1,5 +1,5 @@
1
1
  import type { TonalPalette } from '@material/material-color-utilities';
2
- import { hexFromArgb } from '@material/material-color-utilities';
2
+ import { hexFromArgb } from '@material/material-color-utilities'; // eslint-disable-line import/no-unresolved
3
3
 
4
4
  export function makeColorScheme(opts: {
5
5
  primary: TonalPalette;
@@ -1,5 +1,5 @@
1
1
  import { useMemo, useDeferredValue } from 'react';
2
- import { TonalPalette, argbFromHex } from '@material/material-color-utilities';
2
+ import { TonalPalette, argbFromHex } from '@material/material-color-utilities'; // eslint-disable-line import/no-unresolved
3
3
  import type { Color } from '@basic-ui/color-picker';
4
4
 
5
5
  import { useLocalStorageCachedState } from './useLocalStorageCachedState';