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

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 (37) hide show
  1. package/build/cjs/index.js +109 -16
  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 +27 -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 +17 -6
  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/tsconfig-build.tsbuildinfo +1 -1
  27. package/package.json +2 -2
  28. package/src/Badge/Badge.story.tsx +68 -0
  29. package/src/Badge/Badge.tsx +32 -3
  30. package/src/NavRail/NavRail.story.tsx +1 -45
  31. package/src/NavRail/NavRailItem.tsx +0 -1
  32. package/src/NavRail/icons/test-icons.tsx +46 -0
  33. package/src/Tab/Tab.story.tsx +170 -14
  34. package/src/Tab/Tab.tsx +26 -7
  35. package/src/Tab/TabList.tsx +5 -1
  36. package/src/Tab/context.ts +2 -0
  37. package/src/TabIndicator/TabIndicator.tsx +83 -7
@@ -1,3 +1,4 @@
1
+ import type { RefObject } from 'react';
1
2
  import { forwardRef, useEffect, useRef, useLayoutEffect } from 'react';
2
3
  import { rem } from 'polished';
3
4
  import { assignMultipleRefs } from '@basic-ui/core';
@@ -10,16 +11,29 @@ import { EASING_STANDARD } from '../motion';
10
11
  export interface TabIndicatorProps extends BoxProps {
11
12
  selected?: boolean;
12
13
  color?: string;
14
+ variant: 'primary' | 'secondary';
15
+ labelRef: RefObject<HTMLParagraphElement | null>;
13
16
  }
14
17
 
18
+ const WIDTH_PROPERTY_NAME = '--indicator-width';
19
+ const SCALE_PROPERTY_NAME = '--indicator-scale';
20
+
15
21
  const useEnhancedEffect =
16
22
  typeof window !== 'undefined' ? useLayoutEffect : useEffect;
17
23
 
18
24
  export const TabIndicator = forwardRef<HTMLDivElement, TabIndicatorProps>(
19
25
  function TabIndicator(props, forwardedRef) {
20
- const { as = 'span', selected, color = 'primary', ...otherProps } = props;
26
+ const {
27
+ as = 'span',
28
+ selected,
29
+ color = 'primary',
30
+ variant,
31
+ labelRef,
32
+ ...otherProps
33
+ } = props;
21
34
  const ref = useRef<HTMLSpanElement>(null);
22
35
  const { currentIndicator } = useTabIndicatorContext();
36
+ const resizeObserverRef = useRef<ResizeObserver>();
23
37
 
24
38
  useEnhancedEffect(() => {
25
39
  if (selected && ref.current) {
@@ -28,13 +42,28 @@ export const TabIndicator = forwardRef<HTMLDivElement, TabIndicatorProps>(
28
42
  const previousClientRect =
29
43
  currentIndicator.current.getBoundingClientRect();
30
44
  const currentClientRect = ref.current.getBoundingClientRect();
31
- const widthDelta = previousClientRect.width / currentClientRect.width;
32
45
  const xPosition = previousClientRect.left - currentClientRect.left;
33
46
 
34
47
  const prevTransition = ref.current.style.transition;
35
48
  const prevTransform = ref.current.style.transform;
36
49
  ref.current.style.transition = 'none';
37
- ref.current.style.transform = `translateX(${xPosition}px) scaleX(${widthDelta})`;
50
+ if (variant === 'primary') {
51
+ const prevWidth =
52
+ currentIndicator.current.style.getPropertyValue(
53
+ WIDTH_PROPERTY_NAME
54
+ );
55
+ const currentWidth =
56
+ ref.current.style.getPropertyValue(WIDTH_PROPERTY_NAME);
57
+ const widthDelta = String(
58
+ parseFloat(prevWidth) / parseFloat(currentWidth)
59
+ );
60
+ ref.current.style.setProperty(SCALE_PROPERTY_NAME, widthDelta);
61
+ ref.current.style.transform = `translateX(${xPosition}px)`;
62
+ } else {
63
+ const widthDelta =
64
+ previousClientRect.width / currentClientRect.width;
65
+ ref.current.style.transform = `translateX(${xPosition}px) scaleX(${widthDelta})`;
66
+ }
38
67
 
39
68
  // Force repaint before updating classes and transform to ensure the transform properly takes effect
40
69
  ref.current.getBoundingClientRect();
@@ -42,26 +71,73 @@ export const TabIndicator = forwardRef<HTMLDivElement, TabIndicatorProps>(
42
71
  // Restore and let transition do it's magic
43
72
  ref.current.style.transition = prevTransition;
44
73
  ref.current.style.transform = prevTransform;
74
+ if (variant === 'primary') {
75
+ ref.current.style.setProperty(SCALE_PROPERTY_NAME, '1');
76
+ }
45
77
  }
46
78
  currentIndicator.current = ref.current;
47
79
  }
48
- }, [selected]);
80
+ }, [selected, variant]);
81
+
82
+ useEffect(() => {
83
+ if (variant === 'secondary') {
84
+ return;
85
+ }
86
+
87
+ if (labelRef.current && ref.current) {
88
+ const width = labelRef.current.getBoundingClientRect().width;
89
+ ref.current.style.setProperty(WIDTH_PROPERTY_NAME, `${width}px`);
90
+
91
+ if (typeof ResizeObserver === 'function') {
92
+ resizeObserverRef.current ??= new ResizeObserver(([entry]) => {
93
+ if (ref.current) {
94
+ ref.current.style.setProperty(
95
+ WIDTH_PROPERTY_NAME,
96
+ `${entry.contentRect.width}px`
97
+ );
98
+ }
99
+ });
100
+
101
+ resizeObserverRef.current?.observe(labelRef.current);
102
+ return () => resizeObserverRef.current?.disconnect();
103
+ }
104
+ }
105
+ }, [labelRef, variant]);
49
106
 
50
107
  return (
51
108
  <Box
52
109
  as={as}
53
110
  ref={assignMultipleRefs(ref, forwardedRef)}
54
- width="100%"
55
- height={rem(2)}
56
111
  __css={{
57
112
  bg: color,
58
113
  position: 'absolute',
59
114
  bottom: 0,
60
115
  transform: `scale(1)`,
61
116
  opacity: selected ? 1 : 0,
62
- transformOrigin: 'left',
63
117
  transition: `transform .25s ${EASING_STANDARD}`,
64
118
  zIndex: 1,
119
+ ...(variant === 'secondary'
120
+ ? {
121
+ width: '100%',
122
+ height: rem(2),
123
+ }
124
+ : {
125
+ width: '100%',
126
+ '&::before': {
127
+ content: '""',
128
+ width: `var(${WIDTH_PROPERTY_NAME}, 0px)`,
129
+ height: rem(3),
130
+ borderTopLeftRadius: rem(3),
131
+ borderTopRightRadius: rem(3),
132
+ bg: color,
133
+ position: 'absolute',
134
+ transformOrigin: 'center',
135
+ bottom: 0,
136
+ left: '50%',
137
+ transition: `inherit`,
138
+ transform: `translateX(-50%) scaleX(var(${SCALE_PROPERTY_NAME}, 1))}`,
139
+ },
140
+ }),
65
141
  }}
66
142
  {...otherProps}
67
143
  />