@basic-ui/material 1.0.0-alpha.23 → 1.0.0-alpha.25

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 (40) hide show
  1. package/build/cjs/index.js +134 -20
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/Badge/Badge.d.ts +2 -2
  4. package/build/esm/Badge/Badge.js +28 -2
  5. package/build/esm/Badge/Badge.js.map +1 -1
  6. package/build/esm/Chip/ButtonChip.d.ts +1 -1
  7. package/build/esm/NavRail/NavRailItem.d.ts +3 -3
  8. package/build/esm/NavRail/NavRailItem.js +0 -1
  9. package/build/esm/NavRail/NavRailItem.js.map +1 -1
  10. package/build/esm/NavRail/icons/test-icons.d.ts +4 -0
  11. package/build/esm/NavRail/icons/test-icons.js +42 -0
  12. package/build/esm/NavRail/icons/test-icons.js.map +1 -0
  13. package/build/esm/Tab/Tab.d.ts +1 -1
  14. package/build/esm/Tab/Tab.js +45 -9
  15. package/build/esm/Tab/Tab.js.map +1 -1
  16. package/build/esm/Tab/TabList.d.ts +2 -1
  17. package/build/esm/Tab/TabList.js +5 -2
  18. package/build/esm/Tab/TabList.js.map +1 -1
  19. package/build/esm/Tab/context.d.ts +1 -0
  20. package/build/esm/Tab/context.js +2 -1
  21. package/build/esm/Tab/context.js.map +1 -1
  22. package/build/esm/TabIndicator/TabIndicator.d.ts +4 -2
  23. package/build/esm/TabIndicator/TabIndicator.js +75 -9
  24. package/build/esm/TabIndicator/TabIndicator.js.map +1 -1
  25. package/build/esm/Table/TableHead.d.ts +1 -1
  26. package/build/esm/theme/theme.js +1 -1
  27. package/build/esm/theme/theme.js.map +1 -1
  28. package/build/tsconfig-build.tsbuildinfo +1 -1
  29. package/package.json +3 -3
  30. package/src/Badge/Badge.story.tsx +68 -0
  31. package/src/Badge/Badge.tsx +33 -3
  32. package/src/NavRail/NavRail.story.tsx +1 -45
  33. package/src/NavRail/NavRailItem.tsx +0 -1
  34. package/src/NavRail/icons/test-icons.tsx +46 -0
  35. package/src/Tab/Tab.story.tsx +170 -14
  36. package/src/Tab/Tab.tsx +52 -10
  37. package/src/Tab/TabList.tsx +5 -1
  38. package/src/Tab/context.ts +2 -0
  39. package/src/TabIndicator/TabIndicator.tsx +83 -7
  40. package/src/theme/theme.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basic-ui/material",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.25",
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,7 +27,7 @@
27
27
  "test": "echo \"Error: no test specified\" && exit 1"
28
28
  },
29
29
  "dependencies": {
30
- "@basic-ui/core": "^0.0.49",
30
+ "@basic-ui/core": "^0.0.50",
31
31
  "@basic-ui/dynamic-theme": "^0.0.8",
32
32
  "@styled-system/should-forward-prop": "5.1.5",
33
33
  "@types/styled-system": "^5.1.10",
@@ -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": "3438c9ed529efc9e1a98130719ca372f4c750931"
55
+ "gitHead": "0d58f1872e2d6e046d1f17296322c9a6588a8a57"
56
56
  }
@@ -0,0 +1,68 @@
1
+ import { rem } from 'polished';
2
+ import { useState } from 'react';
3
+
4
+ import { Box } from '../Box';
5
+ import { NavRailIndicator, NavRailItem, NavRailLabel } from '../NavRail';
6
+ import { KitchenIcon, ListIcon, MenuIcon } from '../NavRail/icons/test-icons';
7
+ import { Badge } from './';
8
+
9
+ export default { title: 'components/Badge' };
10
+
11
+ const Example = () => {
12
+ const [selectedItem, setSelectedItem] = useState('0');
13
+
14
+ return (
15
+ <Box
16
+ bg="surface"
17
+ width="80px"
18
+ position="fixed"
19
+ top="0"
20
+ bottom="0"
21
+ left="0"
22
+ py={rem(80)}
23
+ display="flex"
24
+ flexDirection="column"
25
+ px={rem(12)}
26
+ >
27
+ <NavRailItem
28
+ selected={selectedItem === '0'}
29
+ onClick={() => setSelectedItem('0')}
30
+ position="relative"
31
+ >
32
+ <NavRailIndicator>
33
+ <MenuIcon />
34
+ </NavRailIndicator>
35
+ <NavRailLabel>Menu</NavRailLabel>
36
+ <Badge position="absolute" top="-4px" right="-4px" size="small" />
37
+ </NavRailItem>
38
+ <NavRailItem
39
+ selected={selectedItem === '1'}
40
+ onClick={() => setSelectedItem('1')}
41
+ position="relative"
42
+ >
43
+ <NavRailIndicator>
44
+ <KitchenIcon />
45
+ </NavRailIndicator>
46
+ <NavRailLabel>Kitchen</NavRailLabel>
47
+ <Badge position="absolute" top="-4px" right="-4px">
48
+ 9
49
+ </Badge>
50
+ </NavRailItem>
51
+ <NavRailItem
52
+ selected={selectedItem === '2'}
53
+ onClick={() => setSelectedItem('2')}
54
+ position="relative"
55
+ >
56
+ <NavRailIndicator>
57
+ <ListIcon />
58
+ </NavRailIndicator>
59
+ <NavRailLabel>Orders</NavRailLabel>
60
+ <Badge position="absolute" top="-4px" right="-4px">
61
+ 999+
62
+ </Badge>
63
+ </NavRailItem>
64
+ </Box>
65
+ );
66
+ };
67
+
68
+ export const Controlled = () => <Example />;
@@ -1,17 +1,47 @@
1
+ import { rem } from 'polished';
1
2
  import { forwardRef } from 'react';
2
3
 
3
4
  import type { BoxProps } from '../Box';
4
5
  import { Box } from '../Box';
5
6
 
6
7
  export interface BadgeProps extends BoxProps {
7
- placement: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
8
+ size?: 'small' | 'large';
8
9
  }
9
10
 
10
11
  export const Badge = forwardRef<HTMLDivElement, BadgeProps>(function Badge(
11
12
  props,
12
13
  forwardedRef
13
14
  ) {
14
- const { ...otherProps } = props;
15
+ const { size = 'large', __css, ...otherProps } = props;
15
16
 
16
- return <Box ref={forwardedRef} {...otherProps} />;
17
+ return (
18
+ <Box
19
+ ref={forwardedRef}
20
+ __css={{
21
+ variant: 'text.label-small',
22
+ bg: 'error',
23
+ color: 'on.error',
24
+ borderRadius: 'full',
25
+ ...(size === 'small'
26
+ ? {
27
+ maxWidth: rem(6),
28
+ maxHeight: rem(6),
29
+ minWidth: rem(6),
30
+ minHeight: rem(6),
31
+ }
32
+ : {
33
+ px: 1,
34
+ maxHeight: rem(16),
35
+ minWidth: rem(16),
36
+ minHeight: rem(16),
37
+ }),
38
+ display: 'inline-flex',
39
+ alignItems: 'center',
40
+ justifyContent: 'center',
41
+ fontVariantNumeric: 'tabular-nums',
42
+ ...__css,
43
+ }}
44
+ {...otherProps}
45
+ />
46
+ );
17
47
  });
@@ -5,57 +5,13 @@ import { Box } from '../Box';
5
5
  import { NavRailItem, NavRailIndicator, NavRailLabel } from './';
6
6
  import type { NavRailLabelProps } from './';
7
7
  import { EASING_STANDARD } from '../motion';
8
+ import { KitchenIcon, ListIcon, MenuIcon } from './icons/test-icons';
8
9
  // import './styles.css';
9
10
 
10
11
  export default {
11
12
  title: 'components/NavRail',
12
13
  };
13
14
 
14
- const ListIcon = (props) => (
15
- <svg
16
- xmlns="http://www.w3.org/2000/svg"
17
- height={16}
18
- width={16}
19
- viewBox="0 0 24 24"
20
- {...props}
21
- >
22
- <path
23
- fill="currentColor"
24
- 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"
25
- />
26
- </svg>
27
- );
28
-
29
- const KitchenIcon = (props) => (
30
- <svg
31
- xmlns="http://www.w3.org/2000/svg"
32
- height={16}
33
- width={16}
34
- viewBox="0 0 24 24"
35
- {...props}
36
- >
37
- <path
38
- fill="currentColor"
39
- 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"
40
- />
41
- </svg>
42
- );
43
-
44
- const MenuIcon = (props) => (
45
- <svg
46
- xmlns="http://www.w3.org/2000/svg"
47
- height={16}
48
- width={16}
49
- viewBox="0 0 24 24"
50
- {...props}
51
- >
52
- <path
53
- fill="currentColor"
54
- 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"
55
- />
56
- </svg>
57
- );
58
-
59
15
  export const Default = () => {
60
16
  const [selectedItem, setSelectedItem] = useState('0');
61
17
 
@@ -159,7 +159,6 @@ export const NavRailItem = forwardRef<HTMLDivElement, NavRailItemProps>(
159
159
  backgroundColor: 'transparent',
160
160
  margin: 0,
161
161
  padding: 0,
162
- px: rem(12),
163
162
  minHeight: rem(60),
164
163
  height: rem(60),
165
164
  cursor: 'pointer',
@@ -0,0 +1,46 @@
1
+ import type { SVGAttributes } from 'react';
2
+
3
+ export const ListIcon = (props: SVGAttributes<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ height={16}
7
+ width={16}
8
+ viewBox="0 0 24 24"
9
+ {...props}
10
+ >
11
+ <path
12
+ fill="currentColor"
13
+ 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"
14
+ />
15
+ </svg>
16
+ );
17
+
18
+ export const KitchenIcon = (props: SVGAttributes<SVGSVGElement>) => (
19
+ <svg
20
+ xmlns="http://www.w3.org/2000/svg"
21
+ height={16}
22
+ width={16}
23
+ viewBox="0 0 24 24"
24
+ {...props}
25
+ >
26
+ <path
27
+ fill="currentColor"
28
+ 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"
29
+ />
30
+ </svg>
31
+ );
32
+
33
+ export const MenuIcon = (props: SVGAttributes<SVGSVGElement>) => (
34
+ <svg
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ height={16}
37
+ width={16}
38
+ viewBox="0 0 24 24"
39
+ {...props}
40
+ >
41
+ <path
42
+ fill="currentColor"
43
+ 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"
44
+ />
45
+ </svg>
46
+ );
@@ -3,19 +3,114 @@ import { AppBar } from '../AppBar';
3
3
 
4
4
  // import './styles.css';
5
5
 
6
+ const FlightIcon = (props) => (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ height={48}
10
+ width={48}
11
+ viewBox="0 0 48 48"
12
+ {...props}
13
+ >
14
+ <path
15
+ fill="currentColor"
16
+ d="M17.5 44v-2.1l4-3V26.35L4 31.5v-2.9l17.5-10.3V6.5q0-1.05.725-1.775Q22.95 4 24 4q1.05 0 1.775.725.725.725.725 1.775v11.8L44 28.6v2.9l-17.5-5.15V38.9l4 3V44L24 42.15Z"
17
+ />
18
+ </svg>
19
+ );
20
+
21
+ const LuggageIcon = (props) => (
22
+ <svg
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ height={48}
25
+ width={48}
26
+ viewBox="0 0 48 48"
27
+ {...props}
28
+ >
29
+ <path
30
+ fill="currentColor"
31
+ d="M13 42q-1.25 0-2.125-.875T10 39V15.5q0-1.45 1.025-2.475Q12.05 12 13.5 12H18V5.5q0-.7.625-1.1Q19.25 4 20 4h8q.75 0 1.375.4T30 5.5V12h5q1.25 0 2.125.875T38 15v24q0 1.25-.875 2.125T35 42q0 .85-.575 1.425Q33.85 44 33 44q-.85 0-1.425-.575Q31 42.85 31 42H17q0 .85-.575 1.425Q15.85 44 15 44q-.85 0-1.425-.575Q13 42.85 13 42Zm7-30h8V6h-8Zm-7 27h22V15H13v24Zm3.5-3h2V18h-2Zm6.5 0h2V18h-2Zm6.5 0h2V18h-2ZM13 39V15v24Z"
32
+ />
33
+ </svg>
34
+ );
35
+
36
+ const ExploreIcon = (props) => (
37
+ <svg
38
+ xmlns="http://www.w3.org/2000/svg"
39
+ height={48}
40
+ width={48}
41
+ viewBox="0 0 48 48"
42
+ {...props}
43
+ >
44
+ <path
45
+ fill="currentColor"
46
+ d="m13.15 34.85 14.5-7.15 7.15-14.5-14.5 7.15ZM24 26q-.85 0-1.425-.575Q22 24.85 22 24q0-.85.575-1.425Q23.15 22 24 22q.85 0 1.425.575Q26 23.15 26 24q0 .85-.575 1.425Q24.85 26 24 26Zm0 18q-4.1 0-7.75-1.575-3.65-1.575-6.375-4.3-2.725-2.725-4.3-6.375Q4 28.1 4 24q0-4.15 1.575-7.8 1.575-3.65 4.3-6.35 2.725-2.7 6.375-4.275Q19.9 4 24 4q4.15 0 7.8 1.575 3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24q0 4.1-1.575 7.75-1.575 3.65-4.275 6.375t-6.35 4.3Q28.15 44 24 44Zm0-3q7.1 0 12.05-4.975Q41 31.05 41 24q0-7.1-4.95-12.05Q31.1 7 24 7q-7.05 0-12.025 4.95Q7 16.9 7 24q0 7.05 4.975 12.025Q16.95 41 24 41Zm0-17Z"
47
+ />
48
+ </svg>
49
+ );
50
+
51
+ const TuneIcon = (props) => (
52
+ <svg
53
+ xmlns="http://www.w3.org/2000/svg"
54
+ height={48}
55
+ width={48}
56
+ viewBox="0 0 48 48"
57
+ {...props}
58
+ >
59
+ <path
60
+ fill="currentColor"
61
+ d="M21.35 42V30.75h3v4.15H42v3H24.35V42ZM6 37.9v-3h12.35v3Zm9.35-8.3v-4.1H6v-3h9.35v-4.2h3v11.3Zm6-4.1v-3H42v3Zm8.3-8.25V6h3v4.1H42v3h-9.35v4.15ZM6 13.1v-3h20.65v3Z"
62
+ />
63
+ </svg>
64
+ );
65
+
6
66
  export default {
7
67
  title: 'components/Tab',
8
68
  };
9
69
 
10
- const Example = () => {
70
+ const Example = ({ variant }: { variant: 'primary' | 'secondary' }) => {
11
71
  return (
12
72
  <Tabs defaultIndex={0}>
13
73
  <AppBar variant="default" py={0} height={48} elevation="elevated">
14
- <TabList width="100%">
15
- <Tab>Item 1</Tab>
16
- <Tab>Item 2</Tab>
17
- <Tab>Item 3</Tab>
18
- <Tab disabled>Item 4</Tab>
74
+ <TabList width="100%" variant={variant} height="100%">
75
+ <Tab>Flights</Tab>
76
+ <Tab>Trips</Tab>
77
+ <Tab>Explore</Tab>
78
+ <Tab disabled>Settings</Tab>
79
+ </TabList>
80
+ </AppBar>
81
+ <TabPanels>
82
+ <TabPanel>Panel 1</TabPanel>
83
+ <TabPanel>Panel 2</TabPanel>
84
+ <TabPanel>Panel 3</TabPanel>
85
+ <TabPanel>Panel 4</TabPanel>
86
+ </TabPanels>
87
+ </Tabs>
88
+ );
89
+ };
90
+
91
+ const ExampleWithIcons = ({
92
+ variant,
93
+ }: {
94
+ variant: 'primary' | 'secondary';
95
+ }) => {
96
+ return (
97
+ <Tabs defaultIndex={0}>
98
+ <AppBar variant="default" py={0} height={64} elevation="elevated">
99
+ <TabList width="100%" variant={variant} height="100%">
100
+ <Tab>
101
+ <FlightIcon width="24px" height="24px" /> Flights
102
+ </Tab>
103
+ <Tab>
104
+ <LuggageIcon width="24px" height="24px" />
105
+ Trips
106
+ </Tab>
107
+ <Tab>
108
+ <ExploreIcon width="24px" height="24px" />
109
+ Explore
110
+ </Tab>
111
+ <Tab disabled>
112
+ <TuneIcon width="24px" height="24px" /> Settings
113
+ </Tab>
19
114
  </TabList>
20
115
  </AppBar>
21
116
  <TabPanels>
@@ -28,15 +123,62 @@ const Example = () => {
28
123
  );
29
124
  };
30
125
 
31
- const ExampleAppBar = () => {
126
+ const ExampleAppBar = ({ variant }: { variant: 'primary' | 'secondary' }) => {
32
127
  return (
33
128
  <Tabs>
34
129
  <AppBar variant="primary" py={0} height={48} elevation="elevated">
35
- <TabList textColor="on.primary" indicatorColor="surface" width="100%">
36
- <Tab>Item 1</Tab>
37
- <Tab>Item 2</Tab>
38
- <Tab>Item 3</Tab>
39
- <Tab disabled>Item 4</Tab>
130
+ <TabList
131
+ textColor="on.primary"
132
+ indicatorColor="surface"
133
+ width="100%"
134
+ height="100%"
135
+ variant={variant}
136
+ >
137
+ <Tab>Flights</Tab>
138
+ <Tab>Trips</Tab>
139
+ <Tab>Explore</Tab>
140
+ <Tab disabled>Settings</Tab>
141
+ </TabList>
142
+ </AppBar>
143
+ <TabPanels>
144
+ <TabPanel>Panel 1</TabPanel>
145
+ <TabPanel>Panel 2</TabPanel>
146
+ <TabPanel>Panel 3</TabPanel>
147
+ <TabPanel>Panel 4</TabPanel>
148
+ </TabPanels>
149
+ </Tabs>
150
+ );
151
+ };
152
+
153
+ const ExampleAppBarWithIcons = ({
154
+ variant,
155
+ }: {
156
+ variant: 'primary' | 'secondary';
157
+ }) => {
158
+ return (
159
+ <Tabs>
160
+ <AppBar variant="primary" py={0} height={64} elevation="elevated">
161
+ <TabList
162
+ textColor="on.primary"
163
+ indicatorColor="surface"
164
+ width="100%"
165
+ height="100%"
166
+ variant={variant}
167
+ >
168
+ <Tab>
169
+ <FlightIcon width="24px" height="24px" /> Flights
170
+ </Tab>
171
+ <Tab>
172
+ <LuggageIcon width="24px" height="24px" />
173
+ Trips
174
+ </Tab>
175
+ <Tab>
176
+ <ExploreIcon width="24px" height="24px" />
177
+ Explore
178
+ </Tab>
179
+ <Tab disabled>
180
+ <TuneIcon width="24px" height="24px" /> Settings
181
+ </Tab>
40
182
  </TabList>
41
183
  </AppBar>
42
184
  <TabPanels>
@@ -49,5 +191,19 @@ const ExampleAppBar = () => {
49
191
  );
50
192
  };
51
193
 
52
- export const Controlled = () => <Example />;
53
- export const WithAppBar = () => <ExampleAppBar />;
194
+ export const ControlledPrimary = () => <Example variant="primary" />;
195
+ export const ControlledSecondary = () => <Example variant="secondary" />;
196
+ export const ControlledWithIconsPrimary = () => (
197
+ <ExampleWithIcons variant="primary" />
198
+ );
199
+ export const ControlledWithIconsSecondary = () => (
200
+ <ExampleWithIcons variant="secondary" />
201
+ );
202
+ export const WithAppBarPrimary = () => <ExampleAppBar variant="primary" />;
203
+ export const WithAppBarSecondary = () => <ExampleAppBar variant="secondary" />;
204
+ export const WithAppBarWithIconsPrimary = () => (
205
+ <ExampleAppBarWithIcons variant="primary" />
206
+ );
207
+ export const WithAppBarWithIconsSecondary = () => (
208
+ <ExampleAppBarWithIcons variant="secondary" />
209
+ );
package/src/Tab/Tab.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ButtonHTMLAttributes } from 'react';
2
- import { forwardRef } from 'react';
2
+ import { useState, useEffect, useRef, forwardRef } from 'react';
3
3
  import type { TabProps as TabPropsCore } from '@basic-ui/core';
4
4
  import { Tab as TabCore } from '@basic-ui/core';
5
5
  import { rem } from 'polished';
@@ -20,10 +20,23 @@ const TabInner = forwardRef<
20
20
  TabProps & { selected?: boolean }
21
21
  >(function Tab(props, forwardedRef) {
22
22
  const { innerAs, selected, children, disabled, ...otherProps } = props;
23
- const { textColor, indicatorColor, selectedTextColor } = useTabListContext();
23
+ const { textColor, indicatorColor, selectedTextColor, variant } =
24
+ useTabListContext();
25
+ const labelRef = useRef<HTMLParagraphElement>(null);
26
+
27
+ const [mounted, setMounted] = useState(false);
28
+ useEffect(() => {
29
+ setMounted(true);
30
+ }, []);
24
31
 
25
32
  return (
26
- <Box position="relative" display="flex" flex={1} flexDirection="column">
33
+ <Box
34
+ position="relative"
35
+ display="flex"
36
+ flex={1}
37
+ flexDirection="column"
38
+ height="100%"
39
+ >
27
40
  <RippleBox<
28
41
  RippleBoxProps<
29
42
  HTMLButtonElement,
@@ -36,11 +49,12 @@ const TabInner = forwardRef<
36
49
  disabled={disabled}
37
50
  __css={{
38
51
  px: 3,
39
- position: 'relative',
52
+ py: 0,
40
53
  color: selected
41
54
  ? selectedTextColor || indicatorColor
42
55
  : alpha(textColor, disabled ? 0.37 : 0.7),
43
- height: rem(48),
56
+ minHeight: rem(48),
57
+ height: '100%',
44
58
  backgroundColor: 'transparent',
45
59
  border: 'none',
46
60
  ':focus': {
@@ -53,15 +67,43 @@ const TabInner = forwardRef<
53
67
  >
54
68
  <Text
55
69
  as="span"
56
- variant="label-large"
57
- color="inherit"
58
- height="100%"
59
- textAlign="center"
70
+ variant="title-small"
71
+ ref={labelRef}
72
+ __css={{
73
+ display: 'inline-flex',
74
+ justifyContent: 'center',
75
+ alignItems: 'center',
76
+ color: 'inherit',
77
+ height: '100%',
78
+ textAlign: 'center',
79
+ position: 'relative',
80
+ flexDirection: 'column',
81
+ ...(variant === 'primary' &&
82
+ selected &&
83
+ !mounted && {
84
+ '&::before': {
85
+ content: '""',
86
+ bg: indicatorColor,
87
+ position: 'absolute',
88
+ bottom: 0,
89
+ zIndex: 1,
90
+ width: '100%',
91
+ height: rem(3),
92
+ borderTopLeftRadius: rem(3),
93
+ borderTopRightRadius: rem(3),
94
+ },
95
+ }),
96
+ }}
60
97
  >
61
98
  {children}
62
99
  </Text>
63
100
  </RippleBox>
64
- <TabIndicator selected={selected} color={indicatorColor} />
101
+ <TabIndicator
102
+ selected={selected}
103
+ color={indicatorColor}
104
+ variant={variant}
105
+ labelRef={labelRef}
106
+ />
65
107
  </Box>
66
108
  );
67
109
  });
@@ -13,6 +13,7 @@ export type TabListProps = TabListPropsCore &
13
13
  indicatorColor?: string;
14
14
  textColor?: string;
15
15
  selectedTextColor?: string;
16
+ variant?: 'primary' | 'secondary';
16
17
  };
17
18
 
18
19
  const TabListInner = forwardRef<HTMLDivElement, TabListProps>(
@@ -37,12 +38,15 @@ export const TabList = forwardRef<HTMLDivElement, TabListProps>(
37
38
  indicatorColor = 'primary',
38
39
  textColor = 'on.surface',
39
40
  selectedTextColor,
41
+ variant = 'secondary',
40
42
  ...otherProps
41
43
  } = props;
42
44
  const currentIndicator = useRef<HTMLSpanElement>(null);
43
45
 
44
46
  return (
45
- <TabListProvider value={{ indicatorColor, textColor, selectedTextColor }}>
47
+ <TabListProvider
48
+ value={{ indicatorColor, textColor, selectedTextColor, variant }}
49
+ >
46
50
  <TabIndicatorProvider value={{ currentIndicator }}>
47
51
  <TabListCore
48
52
  as={TabListInner}
@@ -5,11 +5,13 @@ export interface TabListContextProps {
5
5
  indicatorColor: string;
6
6
  textColor: string;
7
7
  selectedTextColor?: string;
8
+ variant: 'primary' | 'secondary';
8
9
  }
9
10
 
10
11
  const TabListContext = createContext<TabListContextProps>({
11
12
  indicatorColor: 'primary',
12
13
  textColor: 'on.surface',
14
+ variant: 'secondary',
13
15
  });
14
16
  export const { Provider: TabListProvider } = TabListContext;
15
17
  export const useTabListContext = () => useContext(TabListContext);