@basic-ui/material 1.0.0-alpha.5 → 1.0.0-alpha.8

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 (65) hide show
  1. package/build/cjs/index.js +155 -13
  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/Button/Button.d.ts +1 -1
  7. package/build/esm/Button/ButtonGroup.d.ts +1 -1
  8. package/build/esm/Button/FilledButton.d.ts +1 -1
  9. package/build/esm/Button/FilledButton.js +6 -8
  10. package/build/esm/Button/FilledButton.js.map +1 -1
  11. package/build/esm/Button/OutlinedButton.d.ts +1 -1
  12. package/build/esm/Button/TransparentButton.d.ts +1 -1
  13. package/build/esm/CheckBox/CheckBox.d.ts +1 -1
  14. package/build/esm/Chip/ButtonChip.d.ts +1 -1
  15. package/build/esm/Chip/ChipBase.d.ts +1 -1
  16. package/build/esm/Chip/ChoiceChip.d.ts +1 -1
  17. package/build/esm/Combobox/Combobox.d.ts +7 -7
  18. package/build/esm/Dialog/Dialog.d.ts +1 -1
  19. package/build/esm/Dialog/Scrim.d.ts +1 -1
  20. package/build/esm/Divider/Divider.d.ts +1 -1
  21. package/build/esm/Link/Link.d.ts +1 -1
  22. package/build/esm/ListItem/ListItem.d.ts +1 -1
  23. package/build/esm/Menu/Menu.d.ts +4 -4
  24. package/build/esm/NavRail/NavRailItem.d.ts +15 -0
  25. package/build/esm/NavRail/NavRailItem.js +146 -0
  26. package/build/esm/NavRail/NavRailItem.js.map +1 -0
  27. package/build/esm/NavRail/index.d.ts +1 -0
  28. package/build/esm/NavRail/index.js +2 -0
  29. package/build/esm/NavRail/index.js.map +1 -0
  30. package/build/esm/Paper/Paper.d.ts +1 -1
  31. package/build/esm/Ripple/useRippleSurface.d.ts +2 -2
  32. package/build/esm/Ripple/useRippleSurface.js +61 -58
  33. package/build/esm/Ripple/useRippleSurface.js.map +1 -1
  34. package/build/esm/Select/Select.d.ts +1 -1
  35. package/build/esm/Select/SelectIcon.d.ts +1 -1
  36. package/build/esm/SelectItem/SelectItem.d.ts +1 -1
  37. package/build/esm/SelectionControl/SelectionControlText.d.ts +1 -1
  38. package/build/esm/Skeleton/Skeleton.d.ts +1 -1
  39. package/build/esm/Switch/Switch.d.ts +1 -1
  40. package/build/esm/Tab/Tab.d.ts +1 -1
  41. package/build/esm/Table/TableHead.d.ts +1 -1
  42. package/build/esm/Table/TableRow.d.ts +1 -1
  43. package/build/esm/TextField/FilledContainer.d.ts +1 -1
  44. package/build/esm/TextField/HelperText.d.ts +1 -1
  45. package/build/esm/TextField/Input.d.ts +1 -1
  46. package/build/esm/TextField/TextField.d.ts +1 -1
  47. package/build/esm/Tooltip/Tooltip.d.ts +1 -1
  48. package/build/esm/color.d.ts +2 -0
  49. package/build/esm/color.js +8 -3
  50. package/build/esm/color.js.map +1 -1
  51. package/build/esm/index.d.ts +1 -0
  52. package/build/esm/index.js +1 -0
  53. package/build/esm/index.js.map +1 -1
  54. package/build/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +3 -3
  56. package/src/Button/Button.story.tsx +6 -1
  57. package/src/Button/FilledButton.tsx +4 -9
  58. package/src/NavRail/NavRail.story.tsx +189 -0
  59. package/src/NavRail/NavRailItem.tsx +174 -0
  60. package/src/NavRail/index.ts +1 -0
  61. package/src/Ripple/useRippleSurface.ts +70 -58
  62. package/src/ThemeExplorer/ThemeBuilder.story.tsx +27 -23
  63. package/src/color.ts +25 -4
  64. package/src/index.ts +1 -0
  65. package/src/ThemeExplorer/ThemeExplorer.story.tsx +0 -43
@@ -0,0 +1,189 @@
1
+ import { rem } from 'polished';
2
+ import React, { forwardRef, useState } from 'react';
3
+
4
+ import { Box } from '../Box';
5
+ import { NavRailItem, NavRailIndicator, NavRailLabel } from './';
6
+ import type { NavRailLabelProps } from './';
7
+ // import './styles.css';
8
+
9
+ export default {
10
+ title: 'components/NavRail',
11
+ };
12
+
13
+ const ListIcon = (props) => (
14
+ <svg
15
+ xmlns="http://www.w3.org/2000/svg"
16
+ height={16}
17
+ width={16}
18
+ viewBox="0 0 24 24"
19
+ {...props}
20
+ >
21
+ <path
22
+ fill="currentColor"
23
+ d="M8 17q.425 0 .713-.288Q9 16.425 9 16t-.287-.713Q8.425 15 8 15t-.713.287Q7 15.575 7 16t.287.712Q7.575 17 8 17Zm0-4q.425 0 .713-.288Q9 12.425 9 12t-.287-.713Q8.425 11 8 11t-.713.287Q7 11.575 7 12t.287.712Q7.575 13 8 13Zm0-4q.425 0 .713-.288Q9 8.425 9 8t-.287-.713Q8.425 7 8 7t-.713.287Q7 7.575 7 8t.287.712Q7.575 9 8 9Zm3 8h6v-2h-6Zm0-4h6v-2h-6Zm0-4h6V7h-6ZM5 21q-.825 0-1.413-.587Q3 19.825 3 19V5q0-.825.587-1.413Q4.175 3 5 3h14q.825 0 1.413.587Q21 4.175 21 5v14q0 .825-.587 1.413Q19.825 21 19 21Zm0-2h14V5H5v14ZM5 5v14V5Z"
24
+ />
25
+ </svg>
26
+ );
27
+
28
+ const KitchenIcon = (props) => (
29
+ <svg
30
+ xmlns="http://www.w3.org/2000/svg"
31
+ height={16}
32
+ width={16}
33
+ viewBox="0 0 24 24"
34
+ {...props}
35
+ >
36
+ <path
37
+ fill="currentColor"
38
+ d="M8 8V5h2v3Zm0 9v-5h2v5Zm-2 5q-.825 0-1.412-.587Q4 20.825 4 20V4q0-.825.588-1.413Q5.175 2 6 2h12q.825 0 1.413.587Q20 3.175 20 4v16q0 .825-.587 1.413Q18.825 22 18 22Zm0-2h12v-9H6v9ZM6 9h12V4H6Z"
39
+ />
40
+ </svg>
41
+ );
42
+
43
+ const MenuIcon = (props) => (
44
+ <svg
45
+ xmlns="http://www.w3.org/2000/svg"
46
+ height={16}
47
+ width={16}
48
+ viewBox="0 0 24 24"
49
+ {...props}
50
+ >
51
+ <path
52
+ fill="currentColor"
53
+ d="M17 22v-8h-3V7q0-2.075 1.463-3.537Q16.925 2 19 2v20ZM7 22v-9.15q-1.275-.35-2.137-1.4Q4 10.4 4 9V2h2v7h1V2h2v7h1V2h2v7q0 1.4-.863 2.45-.862 1.05-2.137 1.4V22Z"
54
+ />
55
+ </svg>
56
+ );
57
+
58
+ export const Default = () => {
59
+ const [selectedItem, setSelectedItem] = useState('0');
60
+
61
+ return (
62
+ <Box
63
+ bg="surface"
64
+ width="80px"
65
+ position="fixed"
66
+ top="0"
67
+ bottom="0"
68
+ left="0"
69
+ py={rem(80)}
70
+ display="flex"
71
+ flexDirection="column"
72
+ >
73
+ <NavRailItem
74
+ selected={selectedItem === '0'}
75
+ onClick={() => setSelectedItem('0')}
76
+ >
77
+ <NavRailIndicator>
78
+ <MenuIcon />
79
+ </NavRailIndicator>
80
+ <NavRailLabel>Menu</NavRailLabel>
81
+ </NavRailItem>
82
+ <NavRailItem
83
+ selected={selectedItem === '1'}
84
+ onClick={() => setSelectedItem('1')}
85
+ >
86
+ <NavRailIndicator>
87
+ <KitchenIcon />
88
+ </NavRailIndicator>
89
+ <NavRailLabel>Kitchen</NavRailLabel>
90
+ </NavRailItem>
91
+ <NavRailItem
92
+ selected={selectedItem === '2'}
93
+ onClick={() => setSelectedItem('2')}
94
+ >
95
+ <NavRailIndicator>
96
+ <ListIcon />
97
+ </NavRailIndicator>
98
+ <NavRailLabel>Orders</NavRailLabel>
99
+ </NavRailItem>
100
+ </Box>
101
+ );
102
+ };
103
+
104
+ const DisappearingNavRailLabel = forwardRef<
105
+ HTMLDivElement,
106
+ NavRailLabelProps & { selected: boolean }
107
+ >(function AnimatedNavRailLabel({ selected, height = '28px', ...props }, ref) {
108
+ const transitionDuration = '0.2s';
109
+ const transitionTimingFunction = 'cubic-bezier(0.4, 0, 0.2, 1)';
110
+ return (
111
+ <Box
112
+ ref={ref}
113
+ style={{
114
+ height: selected ? height : '0px',
115
+ }}
116
+ sx={{
117
+ transition: `height ${transitionDuration} ${transitionTimingFunction}`,
118
+ }}
119
+ >
120
+ <NavRailLabel
121
+ style={{
122
+ transform: selected
123
+ ? 'scale(1) translateY(0)'
124
+ : `scale(0.8, 0.64) translateY(calc(${height} * -0.5 * 0.64))`,
125
+ opacity: selected ? '1' : '0',
126
+ }}
127
+ sx={{
128
+ transformOrigin: 'center top',
129
+ transition:
130
+ `transform ${transitionDuration} ${transitionTimingFunction}, ` +
131
+ `opacity ${transitionDuration} ${transitionTimingFunction}`,
132
+ }}
133
+ {...props}
134
+ />
135
+ </Box>
136
+ );
137
+ });
138
+
139
+ export const WithHiddenLabels = () => {
140
+ const [selectedItem, setSelectedItem] = useState('0');
141
+
142
+ return (
143
+ <Box
144
+ bg="surface"
145
+ width="80px"
146
+ position="fixed"
147
+ top="0"
148
+ bottom="0"
149
+ left="0"
150
+ py={rem(80)}
151
+ display="flex"
152
+ flexDirection="column"
153
+ >
154
+ <NavRailItem
155
+ selected={selectedItem === '0'}
156
+ onClick={() => setSelectedItem('0')}
157
+ >
158
+ <NavRailIndicator>
159
+ <MenuIcon />
160
+ </NavRailIndicator>
161
+ <DisappearingNavRailLabel selected={selectedItem === '0'}>
162
+ Menu
163
+ </DisappearingNavRailLabel>
164
+ </NavRailItem>
165
+ <NavRailItem
166
+ selected={selectedItem === '1'}
167
+ onClick={() => setSelectedItem('1')}
168
+ >
169
+ <NavRailIndicator>
170
+ <KitchenIcon />
171
+ </NavRailIndicator>
172
+ <DisappearingNavRailLabel selected={selectedItem === '1'}>
173
+ Kitchen
174
+ </DisappearingNavRailLabel>
175
+ </NavRailItem>
176
+ <NavRailItem
177
+ selected={selectedItem === '2'}
178
+ onClick={() => setSelectedItem('2')}
179
+ >
180
+ <NavRailIndicator>
181
+ <ListIcon />
182
+ </NavRailIndicator>
183
+ <DisappearingNavRailLabel selected={selectedItem === '2'}>
184
+ Orders
185
+ </DisappearingNavRailLabel>
186
+ </NavRailItem>
187
+ </Box>
188
+ );
189
+ };
@@ -0,0 +1,174 @@
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 { useRippleSurface } from '../Ripple';
11
+
12
+ export interface NavRailItemProps extends Omit<BoxProps, 'color'> {
13
+ as?: React.ElementType<any>;
14
+ children?: React.ReactNode;
15
+ disabled?: boolean;
16
+ selected?: boolean;
17
+ color?: string;
18
+ }
19
+
20
+ export type NavRailIndicatorProps = BoxProps;
21
+
22
+ export const NavRailIndicator = forwardRef<
23
+ HTMLDivElement,
24
+ NavRailIndicatorProps
25
+ >(function NavRailIndicator(props, forwardedRef) {
26
+ const { as = 'div', children, __css, ...otherProps } = props;
27
+
28
+ return (
29
+ <Box
30
+ color="currentColor"
31
+ ref={forwardedRef}
32
+ as={as}
33
+ data-nav-rail-item-indicator=""
34
+ {...otherProps}
35
+ __css={{
36
+ width: '100%',
37
+ height: '100%',
38
+ maxWidth: rem(56),
39
+ maxHeight: rem(56),
40
+ borderRadius: 'full',
41
+ bg: 'var(--indicator-background-color)',
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ justifyContent: 'center',
45
+ minHeight: rem(32),
46
+ transition: 'background-color .2s cubic-bezier(.4,0,.2,1)',
47
+ pointerEvents: 'none',
48
+ ...__css,
49
+ }}
50
+ >
51
+ {children}
52
+ </Box>
53
+ );
54
+ });
55
+
56
+ export type NavRailLabelProps = TextProps;
57
+
58
+ export const NavRailLabel = forwardRef<HTMLDivElement, NavRailLabelProps>(
59
+ function NavRailLabel(props, forwardedRef) {
60
+ const { as = 'div', children, __css, ...otherProps } = props;
61
+
62
+ return (
63
+ <Text
64
+ ref={forwardedRef}
65
+ as={as}
66
+ variant="caption"
67
+ lineHeight={1}
68
+ {...otherProps}
69
+ __css={{
70
+ pt: rem(4),
71
+ pb: rem(12),
72
+ color: 'inherit',
73
+ pointerEvents: 'none',
74
+ ...__css,
75
+ }}
76
+ >
77
+ {children}
78
+ </Text>
79
+ );
80
+ }
81
+ );
82
+
83
+ export const NavRailItem = forwardRef<HTMLDivElement, NavRailItemProps>(
84
+ function NavRailItem(props, forwardedRef) {
85
+ const {
86
+ as = 'button',
87
+ children,
88
+ color = 'primary-container',
89
+ selected = false,
90
+ disabled = false,
91
+ style,
92
+ onKeyDown,
93
+ onPointerDown,
94
+ __css,
95
+ ...otherProps
96
+ } = props;
97
+ const theme = useTheme();
98
+ const baseOpacity = 0,
99
+ hoverOpacity = 0.04,
100
+ focusOpacity = 0.12,
101
+ pressedOpacity = 0.12;
102
+ const ripple = useRippleSurface({
103
+ rippleColor: 'currentColor',
104
+ onKeyDown,
105
+ onPointerDown,
106
+ baseOpacity,
107
+ hoverOpacity,
108
+ focusOpacity,
109
+ pressedOpacity,
110
+ });
111
+
112
+ // Apply ripple from nav item to nav indicator
113
+ const rippleCss = useMemo(() => {
114
+ const ret: SxStyleProp = {};
115
+ const keys = Object.keys(ripple.__css);
116
+ for (const key of keys) {
117
+ if (!key.startsWith('&')) {
118
+ ret['& [data-nav-rail-item-indicator]'] =
119
+ ret['& [data-nav-rail-item-indicator]'] || {};
120
+ ret['& [data-nav-rail-item-indicator]'][key] = ripple.__css[key];
121
+ continue;
122
+ }
123
+
124
+ const newKey = key.replace(
125
+ /(.+?)::(before|after)/g,
126
+ '$1 [data-nav-rail-item-indicator]::$2'
127
+ );
128
+ ret[newKey] = ripple.__css[key];
129
+ }
130
+ return ret;
131
+ }, [ripple.__css]);
132
+
133
+ return (
134
+ <Box
135
+ ref={forwardedRef}
136
+ as={as}
137
+ {...otherProps}
138
+ onPointerDown={ripple.onPointerDown}
139
+ onKeyDown={ripple.onKeyDown}
140
+ aria-pressed={selected}
141
+ type="button"
142
+ style={{ ...ripple.style, ...style }}
143
+ disabled={disabled}
144
+ __css={{
145
+ display: 'flex',
146
+ flexDirection: 'column',
147
+ alignItems: 'center',
148
+ transition: 'color .2s cubic-bezier(.4,0,.2,1)',
149
+ color: selected ? `on.${color}` : 'on.surface-variant',
150
+ '--indicator-background-color': selected
151
+ ? get(theme, `colors.${color}`)
152
+ : 'transparent',
153
+ border: 'none',
154
+ ':focus': {
155
+ outline: 'none',
156
+ },
157
+ backgroundColor: 'transparent',
158
+ margin: 0,
159
+ padding: 0,
160
+ px: rem(12),
161
+ minHeight: rem(60),
162
+ height: rem(60),
163
+ cursor: 'pointer',
164
+ textDecoration: 'none',
165
+ WebkitTapHighlightColor: 'transparent',
166
+ ...rippleCss,
167
+ ...__css,
168
+ }}
169
+ >
170
+ {children}
171
+ </Box>
172
+ );
173
+ }
174
+ );
@@ -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,78 @@ 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
+ overflow: 'hidden',
69
+ position: 'relative',
70
+ cursor: 'pointer',
71
+ // fix overflow: hidden + borderRadius in Safari
72
+ // https://gist.github.com/ayamflow/b602ab436ac9f05660d9c15190f4fd7b#gistcomment-2359479
73
+ willChange: 'transform,opacity',
74
+ WebkitTapHighlightColor: 'transparent',
75
+ // ripple overlay
76
+ '&::before': {
77
+ backgroundColor: rippleColor,
78
+ boxSizing: 'content-box',
79
+ position: 'absolute',
80
+ content: '""',
81
+ opacity: baseOpacity,
82
+ pointerEvents: 'none',
83
+ top: '0',
84
+ left: '0',
85
+ width: '100%',
86
+ height: '100%',
87
+ transition: 'opacity 75ms linear',
96
88
  },
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,
89
+ '&:hover::before': {
90
+ opacity: hoverOpacity,
110
91
  },
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,
92
+ '&:focus-visible::before': {
93
+ opacity: focusOpacity,
94
+ },
95
+ ...(!rippleEnabled && {
96
+ '&:active::before': {
97
+ opacity: pressedOpacity,
98
+ },
99
+ }),
100
+ '&[aria-pressed="true"]::before': {
101
+ opacity: baseOpacity + pressedOpacity,
102
+ },
103
+ '&[aria-pressed="true"]:hover::before': {
104
+ opacity: pressedOpacity + hoverOpacity,
117
105
  },
118
- '&:disabled,&[data-disabled]': {
119
- cursor: 'default',
120
- },
121
- // ripple
122
- ...(rippleEnabled && {
123
- '&::after': { ...rippleStyle({ animation }) },
106
+ '&[aria-pressed="true"]:focus-visible::before': {
107
+ opacity: pressedOpacity + focusOpacity,
108
+ },
109
+ ...(!rippleEnabled && {
110
+ '&[aria-pressed="true"]:active::before': {
111
+ opacity: pressedOpacity + pressedOpacity,
112
+ },
113
+ }),
114
+ ['&:disabled::before,&:disabled:hover::before,&:disabled:focus::before,&:disabled:active::before,' +
115
+ '&[data-disabled]::before,&[data-disabled]:hover::before,&[data-disabled]:focus::before,' +
116
+ '&[data-disabled]:active::before,&:disabled[aria-pressed="true"]::before']:
117
+ {
118
+ opacity: 0,
119
+ },
120
+ '&:disabled,&[data-disabled]': {
121
+ cursor: 'default',
122
+ },
123
+ // ripple
124
+ ...(rippleEnabled && {
125
+ '&::after': { ...rippleStyle({ animation }) },
126
+ }),
124
127
  }),
125
- };
128
+ [
129
+ animation,
130
+ baseOpacity,
131
+ focusOpacity,
132
+ hoverOpacity,
133
+ pressedOpacity,
134
+ rippleColor,
135
+ rippleEnabled,
136
+ ]
137
+ );
126
138
 
127
139
  return {
128
140
  style: { ...animationStyle, ...style },
@@ -68,6 +68,8 @@ const ThemeBuilder = () => {
68
68
  sx={{ gap: 3 }}
69
69
  flexDirection="column"
70
70
  width="300px"
71
+ position="fixed"
72
+ top="0"
71
73
  >
72
74
  <Box display="flex">
73
75
  <TextFieldColorPicker
@@ -131,31 +133,33 @@ const ThemeBuilder = () => {
131
133
  </Button>
132
134
  </Box>
133
135
  </Box>
134
- <Box width="600px" mx="auto">
135
- <Box display="flex" flexDirection="column" sx={{ gap: 4 }}>
136
- <Box flex="1">
137
- <Text variant="h5" as="h1" pb={'0.3em'}>
138
- Light theme
139
- </Text>
140
- <ThemeColors scheme={scheme} />
136
+ <Box width="100%" pl="300px">
137
+ <Box width="600px" mx="auto">
138
+ <Box display="flex" flexDirection="column" sx={{ gap: 4 }}>
139
+ <Box flex="1">
140
+ <Text variant="h5" as="h1" pb={'0.3em'}>
141
+ Light theme
142
+ </Text>
143
+ <ThemeColors scheme={scheme} />
144
+ </Box>
145
+ <Box flex="1">
146
+ <Text variant="h5" as="h1" pb={'0.3em'}>
147
+ Dark theme
148
+ </Text>
149
+ <ThemeColors scheme={scheme.modes.dark} />
150
+ </Box>
141
151
  </Box>
142
- <Box flex="1">
143
- <Text variant="h5" as="h1" pb={'0.3em'}>
144
- Dark theme
145
- </Text>
146
- <ThemeColors scheme={scheme.modes.dark} />
152
+ <Box my={4} display="flex" sx={{ gap: 3 }} flexDirection="column">
153
+ <TonalColors palette={a1} />
154
+ <TonalColors palette={secondaryColorTonal} />
155
+ <TonalColors palette={tertiaryColorTonal} />
156
+ <TonalColors palette={error} />
157
+ <TonalColors palette={neutralColorTonal} />
158
+ <TonalColors palette={n2} />
159
+ </Box>
160
+ <Box as="pre" fontFamily="monospace" fontSize="12px">
161
+ {JSON.stringify({ colors: scheme }, null, 2)}
147
162
  </Box>
148
- </Box>
149
- <Box my={4} display="flex" sx={{ gap: 3 }} flexDirection="column">
150
- <TonalColors palette={a1} />
151
- <TonalColors palette={secondaryColorTonal} />
152
- <TonalColors palette={tertiaryColorTonal} />
153
- <TonalColors palette={error} />
154
- <TonalColors palette={neutralColorTonal} />
155
- <TonalColors palette={n2} />
156
- </Box>
157
- <Box as="pre" fontFamily="monospace" fontSize="12px">
158
- {JSON.stringify({ colors: scheme }, null, 2)}
159
163
  </Box>
160
164
  </Box>
161
165
  </Box>
package/src/color.ts CHANGED
@@ -17,17 +17,38 @@ export const alpha =
17
17
  return `rgba(${rgb.red},${rgb.green},${rgb.blue},${alphaValue})`;
18
18
  };
19
19
 
20
+ export function mixColor(
21
+ baseColor: string,
22
+ overlayColor: string
23
+ ): (theme: any) => string;
24
+ export function mixColor(
25
+ baseColor: string,
26
+ overlayColor: string,
27
+ overlayOpacity: number
28
+ ): (theme: any) => string;
29
+ export function mixColor(
30
+ baseColor: string,
31
+ overlayColor: string,
32
+ overlayOpacity?: number
33
+ ): (theme: any) => string {
34
+ return (theme) => {
35
+ baseColor = get(theme, `colors.${baseColor}`, baseColor);
36
+ overlayColor = overlayOpacity
37
+ ? alpha(overlayColor, overlayOpacity)(theme)
38
+ : get(theme, `colors.${overlayColor}`, overlayColor);
39
+
40
+ return `linear-gradient(${overlayColor}, ${overlayColor}), ${baseColor}`;
41
+ };
42
+ }
43
+
20
44
  export function getColorOverlay(
21
45
  theme: Theme,
22
46
  baseColor: string,
23
47
  overlayColor: string,
24
48
  overlayOpacity: number
25
49
  ): SystemStyleObject {
26
- baseColor = get(theme, `colors.${baseColor}`) || baseColor;
27
- overlayColor = alpha(overlayColor, overlayOpacity)(theme);
28
-
29
50
  return {
30
- background: `linear-gradient(${overlayColor}, ${overlayColor}), ${baseColor}`,
51
+ background: mixColor(baseColor, overlayColor, overlayOpacity)(theme),
31
52
  };
32
53
  }
33
54
 
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ export * from './Link';
17
17
  export * from './List';
18
18
  export * from './ListItem';
19
19
  export * from './Menu';
20
+ export * from './NavRail';
20
21
  export * from './NotchedOutline';
21
22
  export * from './Paper';
22
23
  export * from './ProgressSpinner';
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { useTheme } from '@emotion/react';
3
-
4
- import { ThemeColors } from './ThemeColors';
5
- import { DARK_THEME_CLASS, DEFAULT_THEME_CLASS, Box } from '../';
6
-
7
- export default {
8
- title: 'components/ThemeExplorer',
9
- };
10
-
11
- const ThemeExplorer = () => {
12
- const theme = useTheme();
13
- return (
14
- <>
15
- <Box
16
- flex="1"
17
- p={3}
18
- borderRadius="extra-large"
19
- overflow="hidden"
20
- border="1px solid #fff"
21
- borderColor="outline"
22
- bg="surface"
23
- className={DEFAULT_THEME_CLASS}
24
- >
25
- <ThemeColors scheme={theme.colors as any} />
26
- </Box>
27
- <Box
28
- flex="1"
29
- p={3}
30
- borderRadius="extra-large"
31
- overflow="hidden"
32
- border="1px solid #fff"
33
- borderColor="outline"
34
- bg="surface"
35
- className={DARK_THEME_CLASS}
36
- >
37
- <ThemeColors scheme={theme.colors.modes.dark as any} />
38
- </Box>
39
- </>
40
- );
41
- };
42
-
43
- export const Explorer = () => <ThemeExplorer />;