@vectara/vectara-ui 15.7.2 → 15.9.0

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.
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useEffect, useRef } from "react";
13
+ import { useEffect, useRef, useState } from "react";
14
14
  import classNames from "classnames";
15
15
  import { FocusOn } from "react-focus-on";
16
16
  import { BiX } from "react-icons/bi";
@@ -27,21 +27,38 @@ export const VuiDrawer = (_a) => {
27
27
  var { className, color = "primary", title, icon, children, isOpen, onClose, footer } = _a, rest = __rest(_a, ["className", "color", "title", "icon", "children", "isOpen", "onClose", "footer"]);
28
28
  const { DrawerTitle } = useVuiContext();
29
29
  const returnFocusElRef = useRef(null);
30
+ // Uncouple open state from visibile state so that when the popover is closed,
31
+ // we can set the button to be unselected immediately while the popover content
32
+ // is still transitioning out.
33
+ const [showTransition, setShowTransition] = useState(false);
34
+ const [isContentVisible, setIsContentVisible] = useState(false);
30
35
  // Return focus on unmount.
31
36
  useEffect(() => {
32
37
  var _a;
33
38
  if (isOpen) {
34
39
  returnFocusElRef.current = document.activeElement;
40
+ setIsContentVisible(true);
41
+ requestAnimationFrame(() => {
42
+ setShowTransition(true);
43
+ });
35
44
  }
36
45
  else {
37
46
  (_a = returnFocusElRef.current) === null || _a === void 0 ? void 0 : _a.focus();
38
47
  returnFocusElRef.current = null;
48
+ setShowTransition(false);
39
49
  }
40
50
  }, [isOpen]);
41
51
  // Allow contents to respond to blur events before unmounting.
42
52
  const onCloseDelayed = () => {
43
53
  window.setTimeout(() => {
54
+ // First remove the transition class to trigger the exit animation.
55
+ setShowTransition(false);
44
56
  onClose === null || onClose === void 0 ? void 0 : onClose();
57
+ // Wait for the transition to complete before unmounting.
58
+ // This duration should match the CSS transition speed.
59
+ window.setTimeout(() => {
60
+ setIsContentVisible(false);
61
+ }, 200);
45
62
  }, 0);
46
63
  };
47
64
  // Handle outside clicks, but ignore clicks on notifications.
@@ -53,11 +70,13 @@ export const VuiDrawer = (_a) => {
53
70
  }
54
71
  onCloseDelayed();
55
72
  };
56
- const classes = classNames("vuiDrawer", `vuiDrawer--${color}`, className);
57
- return (_jsx(VuiPortal, { children: isOpen && (_jsx(VuiScreenBlock, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: handleClickOutside,
73
+ const classes = classNames("vuiDrawer", `vuiDrawer--${color}`, className, {
74
+ "vuiDrawer-isLoaded": showTransition
75
+ });
76
+ return (_jsx(VuiPortal, { children: (isOpen || isContentVisible || showTransition) && (_jsx(VuiScreenBlock, Object.assign({ isHidden: !isOpen }, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: handleClickOutside,
58
77
  // Enable manual focus return to work.
59
78
  returnFocus: false,
60
79
  // Enable focus on contents when it's open,
61
80
  // but enable manual focus return to work when it's closed.
62
- autoFocus: isOpen }, { children: _jsxs("div", Object.assign({ className: classes }, rest, getOverlayProps("drawerTitle"), { children: [_jsx("div", Object.assign({ className: "vuiDrawerHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiDrawerHeader__title", "data-testid": "drawerTitle" }, { children: _jsx(DrawerTitle, Object.assign({ id: "drawerTitle" }, { children: title })) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Close", "data-testid": "drawerCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiDrawerContent" }, { children: _jsx("div", Object.assign({ className: "vuiDrawerContent__inner" }, { children: children })) })), footer && _jsx("div", Object.assign({ className: "vuiDrawerFooter" }, { children: footer }))] })) })) })) }));
81
+ autoFocus: isOpen }, { children: _jsxs("div", Object.assign({ className: classes }, rest, getOverlayProps("drawerTitle"), { children: [_jsx("div", Object.assign({ className: "vuiDrawerHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiDrawerHeader__title", "data-testid": "drawerTitle" }, { children: _jsx(DrawerTitle, Object.assign({ id: "drawerTitle" }, { children: title })) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Close", "data-testid": "drawerCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiDrawerContent" }, { children: _jsx("div", Object.assign({ className: "vuiDrawerContent__inner" }, { children: children })) })), footer && _jsx("div", Object.assign({ className: "vuiDrawerFooter" }, { children: footer }))] })) })) }))) }));
63
82
  };
@@ -2,16 +2,6 @@
2
2
 
3
3
  $drawerWidth: 680px;
4
4
 
5
- @keyframes drawerIn {
6
- 0% {
7
- right: -$drawerWidth;
8
- }
9
-
10
- 100% {
11
- right: 0;
12
- }
13
- }
14
-
15
5
  .vuiDrawer {
16
6
  display: flex;
17
7
  flex-direction: column;
@@ -24,13 +14,18 @@ $drawerWidth: 680px;
24
14
  background-color: var(--vui-color-empty-shade);
25
15
  border-left: 1px solid var(--vui-color-border-medium);
26
16
  z-index: $drawerZIndex;
27
- animation: drawerIn $transitionSpeed cubic-bezier(0, 1, 0, 1);
17
+ right: -$drawerWidth;
18
+ transition: right $transitionSpeed cubic-bezier(0, 1, 0, 1);
28
19
 
29
- @media screen and (max-width: $drawerWidth + $sizeM) {
20
+ @media screen and (max-width: ($drawerWidth + $sizeM)) {
30
21
  max-width: calc(100% - $sizeM);
31
22
  }
32
23
  }
33
24
 
25
+ .vuiDrawer-isLoaded {
26
+ right: 0;
27
+ }
28
+
34
29
  .vuiDrawerHeader {
35
30
  padding: $sizeS $sizeL;
36
31
  }
@@ -80,6 +80,7 @@ import { VuiTable } from "./table/Table";
80
80
  import { VuiTab } from "./tabs/Tab";
81
81
  import { VuiTabbedRoutes } from "./tabs/TabbedRoutes";
82
82
  import { VuiTabs } from "./tabs/Tabs";
83
+ import { VuiTabsNavigator } from "./tabs/TabNavigator";
83
84
  import { TAB_SIZE, TabSize } from "./tabs/types";
84
85
  import { VuiText } from "./typography/Text";
85
86
  import { VuiTextColor } from "./typography/TextColor";
@@ -88,8 +89,9 @@ import { TEXT_COLOR, TEXT_SIZE, TITLE_SIZE } from "./typography/types";
88
89
  import { VuiTitle } from "./typography/Title";
89
90
  import { VuiToggle } from "./toggle/Toggle";
90
91
  import { VuiTooltip } from "./tooltip/Tooltip";
92
+ import { VuiInfoTooltip } from "./tooltip/InfoTooltip";
91
93
  import { VuiTopicButton } from "./topicButton/TopicButton";
92
94
  import { copyToClipboard } from "../utils/copyToClipboard";
93
95
  import { toRgb, toRgba } from "./context/Theme";
94
96
  export type { AnchorSide, AppContentPadding, ButtonColor, CalloutColor, ChatLanguage, ChatStyle, ChatTurn, CheckboxConfig, CodeEditorColorConfig, CodeEditorError, CodeLanguage, InfoListItemType, InfoListType, InfoTableColumnAlign, InfoTableRow, InfoTableRowType, LinkProps, MenuItem, OptionListItem, Pagination, RadioButtonConfig, SearchResult, SearchSuggestion, Sections, SectionItem, Stat, StepStatus, StepSize, TabSize, Tree, TreeItem, VuiStepProps };
95
- export { BADGE_COLOR, BUTTON_COLOR, BUTTON_SIZE, CALLOUT_COLOR, CALLOUT_SIZE, ICON_COLOR, ICON_SIZE, ICON_TYPE, PROGRESS_BAR_COLOR, SPACER_SIZE, SPINNER_COLOR, SKELETON_COLOR, SPINNER_SIZE, TAB_SIZE, TEXT_COLOR, TEXT_SIZE, TITLE_SIZE, addNotification, copyToClipboard, generateTokensProvider, toRgb, toRgba, VuiAccordion, VuiAccountButton, VuiAppContent, VuiAppHeader, VuiAppLayout, VuiAppSideNav, VuiAppSideNavLink, VuiAppSideNavGroup, VuiBadge, VuiButtonPrimary, VuiButtonSecondary, VuiButtonTertiary, VuiIconButton, VuiCallout, VuiCard, VuiChat, VuiCheckbox, VuiCode, VuiCodeEditor, VuiContextProvider, VuiCopyButton, VuiDatePicker, VuiDateRangePicker, VuiDrawer, VuiErrorBoundary, VuiFlexContainer, VuiFlexItem, VuiFormGroup, VuiGrid, VuiGridItem, VuiHorizontalRule, VuiIcon, VuiImage, VuiImagePreview, VuiInfoList, VuiInfoListItem, VuiInfoMenu, VuiInfoTable, VuiInProgress, VuiItemsInput, VuiLabel, VuiLink, VuiLinkInternal, VuiList, VuiMenu, VuiMenuItem, VuiModal, VuiNotifications, VuiNumberInput, VuiOptionsButton, VuiOptionsList, VuiOptionsListItem, VuiPagination, VuiPanel, VuiPasswordInput, VuiPopover, VuiPortal, VuiProgressBar, VuiPrompt, VuiRadioButton, VuiScreenBlock, VuiSearchInput, VuiSearchResult, VuiSearchSelect, VuiSelect, VuiSetting, VuiSimpleCard, VuiSimpleGrid, VuiSpacer, VuiSpinner, VuiStat, VuiStatList, VuiStatus, VuiSteps, VuiSummary, VuiSkeleton, VuiSummaryCitation, VuiSuperCheckboxGroup, VuiSuperRadioGroup, VuiTable, VuiTab, VuiTabbedRoutes, VuiTabs, VuiText, VuiTextArea, VuiTextColor, VuiTextInput, VuiTimeline, VuiTimelineItem, VuiTitle, VuiToggle, VuiTooltip, VuiTopicButton };
97
+ export { BADGE_COLOR, BUTTON_COLOR, BUTTON_SIZE, CALLOUT_COLOR, CALLOUT_SIZE, ICON_COLOR, ICON_SIZE, ICON_TYPE, PROGRESS_BAR_COLOR, SPACER_SIZE, SPINNER_COLOR, SKELETON_COLOR, SPINNER_SIZE, TAB_SIZE, TEXT_COLOR, TEXT_SIZE, TITLE_SIZE, addNotification, copyToClipboard, generateTokensProvider, toRgb, toRgba, VuiAccordion, VuiAccountButton, VuiAppContent, VuiAppHeader, VuiAppLayout, VuiAppSideNav, VuiAppSideNavLink, VuiAppSideNavGroup, VuiBadge, VuiButtonPrimary, VuiButtonSecondary, VuiButtonTertiary, VuiIconButton, VuiCallout, VuiCard, VuiChat, VuiCheckbox, VuiCode, VuiCodeEditor, VuiContextProvider, VuiCopyButton, VuiDatePicker, VuiDateRangePicker, VuiDrawer, VuiErrorBoundary, VuiFlexContainer, VuiFlexItem, VuiFormGroup, VuiGrid, VuiGridItem, VuiHorizontalRule, VuiIcon, VuiImage, VuiImagePreview, VuiInfoList, VuiInfoListItem, VuiInfoMenu, VuiInfoTable, VuiInfoTooltip, VuiInProgress, VuiItemsInput, VuiLabel, VuiLink, VuiLinkInternal, VuiList, VuiMenu, VuiMenuItem, VuiModal, VuiNotifications, VuiNumberInput, VuiOptionsButton, VuiOptionsList, VuiOptionsListItem, VuiPagination, VuiPanel, VuiPasswordInput, VuiPopover, VuiPortal, VuiProgressBar, VuiPrompt, VuiRadioButton, VuiScreenBlock, VuiSearchInput, VuiSearchResult, VuiSearchSelect, VuiSelect, VuiSetting, VuiSimpleCard, VuiSimpleGrid, VuiSpacer, VuiSpinner, VuiStat, VuiStatList, VuiStatus, VuiSteps, VuiSummary, VuiSkeleton, VuiSummaryCitation, VuiSuperCheckboxGroup, VuiSuperRadioGroup, VuiTable, VuiTab, VuiTabbedRoutes, VuiTabs, VuiTabsNavigator, VuiText, VuiTextArea, VuiTextColor, VuiTextInput, VuiTimeline, VuiTimelineItem, VuiTitle, VuiToggle, VuiTooltip, VuiTopicButton };
@@ -73,6 +73,7 @@ import { VuiTable } from "./table/Table";
73
73
  import { VuiTab } from "./tabs/Tab";
74
74
  import { VuiTabbedRoutes } from "./tabs/TabbedRoutes";
75
75
  import { VuiTabs } from "./tabs/Tabs";
76
+ import { VuiTabsNavigator } from "./tabs/TabNavigator";
76
77
  import { TAB_SIZE } from "./tabs/types";
77
78
  import { VuiText } from "./typography/Text";
78
79
  import { VuiTextColor } from "./typography/TextColor";
@@ -81,7 +82,8 @@ import { TEXT_COLOR, TEXT_SIZE, TITLE_SIZE } from "./typography/types";
81
82
  import { VuiTitle } from "./typography/Title";
82
83
  import { VuiToggle } from "./toggle/Toggle";
83
84
  import { VuiTooltip } from "./tooltip/Tooltip";
85
+ import { VuiInfoTooltip } from "./tooltip/InfoTooltip";
84
86
  import { VuiTopicButton } from "./topicButton/TopicButton";
85
87
  import { copyToClipboard } from "../utils/copyToClipboard";
86
88
  import { toRgb, toRgba } from "./context/Theme";
87
- export { BADGE_COLOR, BUTTON_COLOR, BUTTON_SIZE, CALLOUT_COLOR, CALLOUT_SIZE, ICON_COLOR, ICON_SIZE, ICON_TYPE, PROGRESS_BAR_COLOR, SPACER_SIZE, SPINNER_COLOR, SKELETON_COLOR, SPINNER_SIZE, TAB_SIZE, TEXT_COLOR, TEXT_SIZE, TITLE_SIZE, addNotification, copyToClipboard, generateTokensProvider, toRgb, toRgba, VuiAccordion, VuiAccountButton, VuiAppContent, VuiAppHeader, VuiAppLayout, VuiAppSideNav, VuiAppSideNavLink, VuiAppSideNavGroup, VuiBadge, VuiButtonPrimary, VuiButtonSecondary, VuiButtonTertiary, VuiIconButton, VuiCallout, VuiCard, VuiChat, VuiCheckbox, VuiCode, VuiCodeEditor, VuiContextProvider, VuiCopyButton, VuiDatePicker, VuiDateRangePicker, VuiDrawer, VuiErrorBoundary, VuiFlexContainer, VuiFlexItem, VuiFormGroup, VuiGrid, VuiGridItem, VuiHorizontalRule, VuiIcon, VuiImage, VuiImagePreview, VuiInfoList, VuiInfoListItem, VuiInfoMenu, VuiInfoTable, VuiInProgress, VuiItemsInput, VuiLabel, VuiLink, VuiLinkInternal, VuiList, VuiMenu, VuiMenuItem, VuiModal, VuiNotifications, VuiNumberInput, VuiOptionsButton, VuiOptionsList, VuiOptionsListItem, VuiPagination, VuiPanel, VuiPasswordInput, VuiPopover, VuiPortal, VuiProgressBar, VuiPrompt, VuiRadioButton, VuiScreenBlock, VuiSearchInput, VuiSearchResult, VuiSearchSelect, VuiSelect, VuiSetting, VuiSimpleCard, VuiSimpleGrid, VuiSpacer, VuiSpinner, VuiStat, VuiStatList, VuiStatus, VuiSteps, VuiSummary, VuiSkeleton, VuiSummaryCitation, VuiSuperCheckboxGroup, VuiSuperRadioGroup, VuiTable, VuiTab, VuiTabbedRoutes, VuiTabs, VuiText, VuiTextArea, VuiTextColor, VuiTextInput, VuiTimeline, VuiTimelineItem, VuiTitle, VuiToggle, VuiTooltip, VuiTopicButton };
89
+ export { BADGE_COLOR, BUTTON_COLOR, BUTTON_SIZE, CALLOUT_COLOR, CALLOUT_SIZE, ICON_COLOR, ICON_SIZE, ICON_TYPE, PROGRESS_BAR_COLOR, SPACER_SIZE, SPINNER_COLOR, SKELETON_COLOR, SPINNER_SIZE, TAB_SIZE, TEXT_COLOR, TEXT_SIZE, TITLE_SIZE, addNotification, copyToClipboard, generateTokensProvider, toRgb, toRgba, VuiAccordion, VuiAccountButton, VuiAppContent, VuiAppHeader, VuiAppLayout, VuiAppSideNav, VuiAppSideNavLink, VuiAppSideNavGroup, VuiBadge, VuiButtonPrimary, VuiButtonSecondary, VuiButtonTertiary, VuiIconButton, VuiCallout, VuiCard, VuiChat, VuiCheckbox, VuiCode, VuiCodeEditor, VuiContextProvider, VuiCopyButton, VuiDatePicker, VuiDateRangePicker, VuiDrawer, VuiErrorBoundary, VuiFlexContainer, VuiFlexItem, VuiFormGroup, VuiGrid, VuiGridItem, VuiHorizontalRule, VuiIcon, VuiImage, VuiImagePreview, VuiInfoList, VuiInfoListItem, VuiInfoMenu, VuiInfoTable, VuiInfoTooltip, VuiInProgress, VuiItemsInput, VuiLabel, VuiLink, VuiLinkInternal, VuiList, VuiMenu, VuiMenuItem, VuiModal, VuiNotifications, VuiNumberInput, VuiOptionsButton, VuiOptionsList, VuiOptionsListItem, VuiPagination, VuiPanel, VuiPasswordInput, VuiPopover, VuiPortal, VuiProgressBar, VuiPrompt, VuiRadioButton, VuiScreenBlock, VuiSearchInput, VuiSearchResult, VuiSearchSelect, VuiSelect, VuiSetting, VuiSimpleCard, VuiSimpleGrid, VuiSpacer, VuiSpinner, VuiStat, VuiStatList, VuiStatus, VuiSteps, VuiSummary, VuiSkeleton, VuiSummaryCitation, VuiSuperCheckboxGroup, VuiSuperRadioGroup, VuiTable, VuiTab, VuiTabbedRoutes, VuiTabs, VuiTabsNavigator, VuiText, VuiTextArea, VuiTextColor, VuiTextInput, VuiTimeline, VuiTimelineItem, VuiTitle, VuiToggle, VuiTooltip, VuiTopicButton };
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useEffect, useRef } from "react";
13
+ import { useEffect, useRef, useState } from "react";
14
14
  import classNames from "classnames";
15
15
  import { FocusOn } from "react-focus-on";
16
16
  import { BiX } from "react-icons/bi";
@@ -27,28 +27,48 @@ export const VuiModal = (_a) => {
27
27
  var { className, color = "primary", title, icon, children, isOpen, onClose, key, canClickOutsideToClose = true, size = "s" } = _a, rest = __rest(_a, ["className", "color", "title", "icon", "children", "isOpen", "onClose", "key", "canClickOutsideToClose", "size"]);
28
28
  const { DrawerTitle } = useVuiContext();
29
29
  const returnFocusElRef = useRef(null);
30
+ // Uncouple open state from visibile state so that when the popover is closed,
31
+ // we can set the button to be unselected immediately while the popover content
32
+ // is still transitioning out.
33
+ const [showTransition, setShowTransition] = useState(false);
34
+ const [isContentVisible, setIsContentVisible] = useState(false);
30
35
  // Return focus on unmount.
31
36
  useEffect(() => {
32
37
  var _a;
33
38
  if (isOpen) {
34
39
  returnFocusElRef.current = document.activeElement;
40
+ setIsContentVisible(true);
41
+ requestAnimationFrame(() => {
42
+ setShowTransition(true);
43
+ });
35
44
  }
36
45
  else {
37
46
  (_a = returnFocusElRef.current) === null || _a === void 0 ? void 0 : _a.focus();
38
47
  returnFocusElRef.current = null;
48
+ setShowTransition(false);
39
49
  }
40
50
  }, [isOpen]);
41
51
  // Allow contents to respond to blur events before unmounting.
42
52
  const onCloseDelayed = () => {
43
53
  window.setTimeout(() => {
54
+ // First remove the transition class to trigger the exit animation.
55
+ setShowTransition(false);
44
56
  onClose === null || onClose === void 0 ? void 0 : onClose();
57
+ // Wait for the transition to complete before unmounting.
58
+ // This duration should match the CSS transition speed.
59
+ window.setTimeout(() => {
60
+ setIsContentVisible(false);
61
+ }, 200);
45
62
  }, 0);
46
63
  };
64
+ const containerClasses = classNames("vuiModalContainer", {
65
+ "vuiModalContainer-isLoaded": showTransition
66
+ });
47
67
  const classes = classNames("vuiModal", `vuiModal--${color}`, `vuiModal--${size}`, className);
48
- return (_jsx(VuiPortal, { children: isOpen && (_jsx(VuiScreenBlock, Object.assign({ type: "modal" }, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: canClickOutsideToClose ? onCloseDelayed : undefined,
68
+ return (_jsx(VuiPortal, { children: (isOpen || isContentVisible || showTransition) && (_jsx(VuiScreenBlock, Object.assign({ type: "modal", isHidden: !isOpen }, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: canClickOutsideToClose ? onCloseDelayed : undefined,
49
69
  // Enable manual focus return to work.
50
70
  returnFocus: false,
51
71
  // Enable focus on contents when it's open,
52
72
  // but enable manual focus return to work when it's closed.
53
- autoFocus: isOpen }, { children: _jsx("div", Object.assign({ className: "vuiModalContainer" }, getOverlayProps("modalTitle"), { children: _jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsx("div", Object.assign({ className: "vuiModalHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiModalHeader__title" }, { children: _jsx(DrawerTitle, Object.assign({ id: "modalTitle" }, { children: title })) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Close", "data-testid": "modalCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiModalContent" }, { children: _jsx("div", Object.assign({ className: "vuiModalContent__inner" }, { children: children })) }))] })) })) })) }), key)) }));
73
+ autoFocus: isOpen }, { children: _jsx("div", Object.assign({ className: containerClasses }, getOverlayProps("modalTitle"), { children: _jsxs("div", Object.assign({ className: classes }, rest, { children: [_jsx("div", Object.assign({ className: "vuiModalHeader" }, { children: _jsxs(VuiFlexContainer, Object.assign({ justifyContent: "spaceBetween", alignItems: "center" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [icon && (_jsx(VuiFlexItem, Object.assign({ grow: false, shrink: false }, { children: _jsx(VuiIcon, Object.assign({ size: "l" }, { children: icon })) }))), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiModalHeader__title" }, { children: _jsx(DrawerTitle, Object.assign({ id: "modalTitle" }, { children: title })) })) }))] })) })), onClose && (_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Close", "data-testid": "modalCloseButton", onClick: onCloseDelayed, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "neutral" }, { children: _jsx(BiX, {}) })) }) }))] })) })), _jsx("div", Object.assign({ className: "vuiModalContent" }, { children: _jsx("div", Object.assign({ className: "vuiModalContent__inner" }, { children: children })) }))] })) })) })) }), key)) }));
54
74
  };
@@ -1,17 +1,5 @@
1
1
  @use "sass:map";
2
2
 
3
- @keyframes modalIn {
4
- 0% {
5
- transform: translateY(12px);
6
- opacity: 0;
7
- }
8
-
9
- 100% {
10
- transform: translateY(0);
11
- opacity: 1;
12
- }
13
- }
14
-
15
3
  .vuiModalContainer {
16
4
  position: fixed;
17
5
  top: 0;
@@ -21,10 +9,17 @@
21
9
  display: flex;
22
10
  justify-content: center;
23
11
  align-items: center;
24
- animation: modalIn $transitionSpeed cubic-bezier(0, 1, 1, 1);
12
+ transform: translateY(12px);
13
+ opacity: 0;
14
+ transition: transform $transitionSpeed cubic-bezier(0, 1, 1, 1), opacity $transitionSpeed;
25
15
  pointer-events: none;
26
16
  }
27
17
 
18
+ .vuiModalContainer-isLoaded {
19
+ transform: translateY(0);
20
+ opacity: 1;
21
+ }
22
+
28
23
  .vuiModal {
29
24
  display: flex;
30
25
  flex-direction: column;
@@ -8,7 +8,7 @@ export type Props = {
8
8
  isOpen: boolean;
9
9
  setIsOpen: (isOpen: boolean) => void;
10
10
  onClickButton?: (e: React.MouseEvent<HTMLElement>) => void;
11
- padding?: boolean;
11
+ padding?: boolean | "none";
12
12
  anchorSide?: AnchorSide;
13
13
  anchorOffsetX?: number;
14
14
  anchorOffsetY?: number;
@@ -69,6 +69,10 @@ export const VuiPopover = (_a) => {
69
69
  const buttonRef = useRef(null);
70
70
  const [, setPositionMarker] = useState(0);
71
71
  const [showTransition, setShowTransition] = useState(false);
72
+ // Uncouple open state from visibile state so that when the popover is closed,
73
+ // we can set the button to be unselected immediately while the popover content
74
+ // is still transitioning out.
75
+ const [isContentVisible, setIsContentVisible] = useState(false);
72
76
  const buttonProps = {
73
77
  ref: (node) => {
74
78
  buttonRef.current = node;
@@ -120,6 +124,7 @@ export const VuiPopover = (_a) => {
120
124
  var _a;
121
125
  if (isOpen) {
122
126
  returnFocusElRef.current = document.activeElement;
127
+ setIsContentVisible(true);
123
128
  requestAnimationFrame(() => {
124
129
  setShowTransition(true);
125
130
  });
@@ -127,6 +132,7 @@ export const VuiPopover = (_a) => {
127
132
  else {
128
133
  (_a = returnFocusElRef.current) === null || _a === void 0 ? void 0 : _a.focus();
129
134
  returnFocusElRef.current = null;
135
+ setShowTransition(false);
130
136
  }
131
137
  }, [isOpen]);
132
138
  // Allow contents to respond to blur events before unmounting, and also
@@ -134,8 +140,14 @@ export const VuiPopover = (_a) => {
134
140
  // outside of the popover.
135
141
  const onCloseDelayed = () => {
136
142
  window.setTimeout(() => {
137
- setIsOpen(false);
143
+ // First remove the transition class to trigger the exit animation.
138
144
  setShowTransition(false);
145
+ setIsOpen(false);
146
+ // Wait for the transition to complete before unmounting.
147
+ // This duration should match the CSS transition speed.
148
+ window.setTimeout(() => {
149
+ setIsContentVisible(false);
150
+ }, 200);
139
151
  }, 0);
140
152
  };
141
153
  // Always keep menu position up to date. If we tried to cache this inside
@@ -154,9 +166,10 @@ export const VuiPopover = (_a) => {
154
166
  "vuiPopover--upRight": anchorSide === "upRight"
155
167
  });
156
168
  const contentClasses = classNames("vuiPopoverContent", {
157
- "vuiPopoverContent--padding": padding
169
+ "vuiPopoverContent--padding": padding === true,
170
+ "vuiPopoverContent--paddingNone": padding === "none"
158
171
  });
159
- return (_jsxs(_Fragment, { children: [button, _jsx(VuiPortal, { children: isOpen && position && (_jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: onCloseDelayed,
172
+ return (_jsxs(_Fragment, { children: [button, _jsx(VuiPortal, { children: (isOpen || isContentVisible || showTransition) && position && (_jsx(FocusOn, Object.assign({ onEscapeKey: onCloseDelayed, onClickOutside: onCloseDelayed,
160
173
  // Enable manual focus return to work.
161
174
  returnFocus: false,
162
175
  // Enable focus on contents when it's open,
@@ -9,7 +9,11 @@
9
9
  opacity: 0;
10
10
  transform: translateY(-$sizeXs);
11
11
  transition: opacity $transitionSpeed, transform $transitionSpeed;
12
- visibility: hidden;
12
+ }
13
+
14
+ .vuiPopover-isLoaded {
15
+ opacity: 1;
16
+ transform: translateY(0);
13
17
  }
14
18
 
15
19
  .vuiPopover--allowOverflow {
@@ -23,12 +27,6 @@
23
27
 
24
28
  .vuiPopover--upLeft,
25
29
  .vuiPopover--upRight {
26
- transform: translateY($sizeXs);
27
- }
28
-
29
- .vuiPopover-isLoaded {
30
- visibility: visible;
31
- opacity: 1;
32
30
  transform: translateY(0);
33
31
  }
34
32
 
@@ -51,3 +49,7 @@
51
49
  .vuiPopoverContent--padding {
52
50
  padding: $sizeS;
53
51
  }
52
+
53
+ .vuiPopoverContent--paddingNone {
54
+ padding: 0;
55
+ }
@@ -3,6 +3,7 @@ type Props = {
3
3
  children: React.ReactNode;
4
4
  color?: "neutral" | "primary" | "danger" | "success";
5
5
  type?: "default" | "modal";
6
+ isHidden?: boolean;
6
7
  };
7
- export declare const VuiScreenBlock: ({ onClick, children, color, type }: Props) => import("react/jsx-runtime").JSX.Element;
8
+ export declare const VuiScreenBlock: ({ onClick, children, color, type, isHidden }: Props) => import("react/jsx-runtime").JSX.Element;
8
9
  export {};
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import classNames from "classnames";
3
- export const VuiScreenBlock = ({ onClick, children, color = "neutral", type = "default" }) => {
4
- const classes = classNames("vuiScreenBlock", `vuiScreenBlock--${color}`, `vuiScreenBlock--${type}`);
3
+ export const VuiScreenBlock = ({ onClick, children, color = "neutral", type = "default", isHidden = false }) => {
4
+ const classes = classNames("vuiScreenBlock", `vuiScreenBlock--${color}`, `vuiScreenBlock--${type}`, isHidden && "vuiScreenBlock-isHidden");
5
5
  return (_jsxs("div", Object.assign({ className: classes }, { children: [children, _jsx("div", { className: "vuiScreenBlock__mask", onClick: onClick })] })));
6
6
  };
@@ -7,6 +7,14 @@
7
7
  display: flex;
8
8
  align-items: center;
9
9
  justify-content: center;
10
+ pointer-events: initial;
11
+ opacity: 1;
12
+ transition: opacity $transitionSpeed;
13
+ }
14
+
15
+ .vuiScreenBlock-isHidden {
16
+ pointer-events: none;
17
+ opacity: 0;
10
18
  }
11
19
 
12
20
  .vuiScreenBlock--default {
@@ -0,0 +1,8 @@
1
+ import { Props as PopoverProps } from "../popover/Popover";
2
+ import { TabRoute } from "./types";
3
+ type Props = {
4
+ routes: TabRoute[];
5
+ popover?: Omit<PopoverProps, "header" | "isOpen" | "setIsOpen" | "button" | "children" | "padding">;
6
+ };
7
+ export declare const VuiTabsNavigator: ({ routes, popover }: Props) => import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { VuiPopover } from "../popover/Popover";
4
+ import { VuiTab } from "./Tab";
5
+ import { VuiTabs } from "./Tabs";
6
+ import { useVuiContext } from "../context/Context";
7
+ export const VuiTabsNavigator = ({ routes, popover }) => {
8
+ var _a;
9
+ const { getPath } = useVuiContext();
10
+ const [isOpen, setIsOpen] = useState(false);
11
+ const activeRoute = routes.find((route) => route.isActive || getPath().includes(route.href));
12
+ return (_jsx(VuiPopover, Object.assign({}, popover, { isOpen: isOpen, setIsOpen: () => setIsOpen(!isOpen), button: _jsx("div", Object.assign({ className: "vuiTabs vuiTabs--s vuiTabs--enclosed" }, { children: _jsx(VuiTab, Object.assign({ isActive: true }, { children: (_a = activeRoute === null || activeRoute === void 0 ? void 0 : activeRoute.title) !== null && _a !== void 0 ? _a : "No selection" })) })), padding: "none" }, { children: _jsx(VuiTabs, Object.assign({ size: "s", tabStyle: "enclosed" }, { children: routes.map(({ href, title, render, testId, isActive }, index) => {
13
+ const tabLink = (_jsx(VuiTab, Object.assign({ href: href, isActive: isActive !== null && isActive !== void 0 ? isActive : getPath().includes(href), "data-testid": testId, onClick: () => setIsOpen(false) }, { children: title }), index));
14
+ if (render)
15
+ return render(tabLink);
16
+ return tabLink;
17
+ }) })) })));
18
+ };
@@ -1,12 +1,6 @@
1
- import { TabSize } from "./types";
1
+ import { TabRoute, TabSize } from "./types";
2
2
  type Props = {
3
- tabs: Array<{
4
- href: string;
5
- title: string;
6
- render?: (tabLink: React.ReactNode) => React.ReactNode;
7
- component: React.ReactNode;
8
- testId?: string;
9
- }>;
3
+ tabs: TabRoute[];
10
4
  size?: TabSize;
11
5
  sideContent?: React.ReactNode;
12
6
  children?: React.ReactNode;
@@ -5,9 +5,8 @@ import { VuiSpacer } from "../spacer/Spacer";
5
5
  import { useVuiContext } from "../context/Context";
6
6
  export const VuiTabbedRoutes = ({ tabs, size, sideContent, children }) => {
7
7
  const { getPath } = useVuiContext();
8
- return (_jsxs(_Fragment, { children: [_jsx(VuiTabs, Object.assign({ append: sideContent, size: size }, { children: tabs.map(({ href, title, render, testId }, index) => {
9
- const isActive = getPath().includes(href);
10
- const tabLink = (_jsx(VuiTab, Object.assign({ href: href, isActive: isActive, "data-testid": testId }, { children: title }), index));
8
+ return (_jsxs(_Fragment, { children: [_jsx(VuiTabs, Object.assign({ append: sideContent, size: size }, { children: tabs.map(({ href, title, render, testId, isActive }, index) => {
9
+ const tabLink = (_jsx(VuiTab, Object.assign({ href: href, isActive: isActive !== null && isActive !== void 0 ? isActive : getPath().includes(href), "data-testid": testId }, { children: title }), index));
11
10
  if (render)
12
11
  return render(tabLink);
13
12
  return tabLink;
@@ -1,2 +1,9 @@
1
1
  export declare const TAB_SIZE: readonly ["s", "m"];
2
2
  export type TabSize = (typeof TAB_SIZE)[number];
3
+ export type TabRoute = {
4
+ href: string;
5
+ title: string;
6
+ render?: (tabLink: React.ReactNode) => React.ReactNode;
7
+ testId?: string;
8
+ isActive?: boolean;
9
+ };
@@ -0,0 +1,4 @@
1
+ import { Props as TooltipProps } from "./Tooltip";
2
+ type Props = Omit<TooltipProps, "children">;
3
+ export declare const VuiInfoTooltip: (props: Props) => import("react/jsx-runtime").JSX.Element;
4
+ export {};
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BiHelpCircle } from "react-icons/bi";
3
+ import { VuiIcon } from "../icon/Icon";
4
+ import { VuiTooltip } from "./Tooltip";
5
+ export const VuiInfoTooltip = (props) => {
6
+ return (_jsx(VuiTooltip, Object.assign({}, props, { children: _jsx(VuiIcon, Object.assign({ color: "subdued", size: "s" }, { children: _jsx(BiHelpCircle, {}) })) })));
7
+ };
@@ -6,12 +6,30 @@ import { VuiPortal } from "../portal/Portal";
6
6
  const generateTooltipId = () => {
7
7
  return `tooltip-${Math.random().toString(36).slice(2, 9)}`;
8
8
  };
9
+ // Naturally focusable elements that don't need tabIndex.
10
+ const FOCUSABLE_ELEMENTS = ["a", "button", "input", "select", "textarea"];
11
+ // Determine if the element needs tabIndex to be keyboard accessible.
12
+ const needsTabIndex = (element) => {
13
+ var _a;
14
+ if (!element || typeof element !== "object" || !("type" in element)) {
15
+ return false;
16
+ }
17
+ const child = element;
18
+ const elementType = typeof child.type === "string" ? child.type.toLowerCase() : "";
19
+ // Don't add tabIndex if element is naturally focusable.
20
+ if (FOCUSABLE_ELEMENTS.includes(elementType)) {
21
+ return false;
22
+ }
23
+ // Don't add tabIndex if it already has one.
24
+ if (((_a = child.props) === null || _a === void 0 ? void 0 : _a.tabIndex) !== undefined) {
25
+ return false;
26
+ }
27
+ return true;
28
+ };
9
29
  export const VuiTooltip = ({ children, darkTheme, position, tip, usePortal }) => {
10
30
  const { getThemeStyle } = useVuiContext();
11
31
  const [id] = useState(generateTooltipId());
12
- const target = cloneElement(children, {
13
- "data-tooltip-id": id
14
- });
32
+ const target = cloneElement(children, Object.assign({ "data-tooltip-id": id }, (needsTabIndex(children) && { tabIndex: 0 })));
15
33
  // Tooltips can be used in a dark-themed component, so we need to explicitly set
16
34
  // the light theme class in order to enable having a different theme than the
17
35
  // parent.
@@ -2423,14 +2423,6 @@ h2.react-datepicker__current-month {
2423
2423
  right: 4px;
2424
2424
  }
2425
2425
 
2426
- @keyframes drawerIn {
2427
- 0% {
2428
- right: -680px;
2429
- }
2430
- 100% {
2431
- right: 0;
2432
- }
2433
- }
2434
2426
  .vuiDrawer {
2435
2427
  display: flex;
2436
2428
  flex-direction: column;
@@ -2443,7 +2435,8 @@ h2.react-datepicker__current-month {
2443
2435
  background-color: var(--vui-color-empty-shade);
2444
2436
  border-left: 1px solid var(--vui-color-border-medium);
2445
2437
  z-index: 11;
2446
- animation: drawerIn 0.2s cubic-bezier(0, 1, 0, 1);
2438
+ right: -680px;
2439
+ transition: right 0.2s cubic-bezier(0, 1, 0, 1);
2447
2440
  }
2448
2441
  @media screen and (max-width: 696px) {
2449
2442
  .vuiDrawer {
@@ -2451,6 +2444,10 @@ h2.react-datepicker__current-month {
2451
2444
  }
2452
2445
  }
2453
2446
 
2447
+ .vuiDrawer-isLoaded {
2448
+ right: 0;
2449
+ }
2450
+
2454
2451
  .vuiDrawerHeader {
2455
2452
  padding: 12px 24px;
2456
2453
  }
@@ -3966,16 +3963,6 @@ h2.react-datepicker__current-month {
3966
3963
  line-height: 1.4;
3967
3964
  }
3968
3965
 
3969
- @keyframes modalIn {
3970
- 0% {
3971
- transform: translateY(12px);
3972
- opacity: 0;
3973
- }
3974
- 100% {
3975
- transform: translateY(0);
3976
- opacity: 1;
3977
- }
3978
- }
3979
3966
  .vuiModalContainer {
3980
3967
  position: fixed;
3981
3968
  top: 0;
@@ -3985,10 +3972,17 @@ h2.react-datepicker__current-month {
3985
3972
  display: flex;
3986
3973
  justify-content: center;
3987
3974
  align-items: center;
3988
- animation: modalIn 0.2s cubic-bezier(0, 1, 1, 1);
3975
+ transform: translateY(12px);
3976
+ opacity: 0;
3977
+ transition: transform 0.2s cubic-bezier(0, 1, 1, 1), opacity 0.2s;
3989
3978
  pointer-events: none;
3990
3979
  }
3991
3980
 
3981
+ .vuiModalContainer-isLoaded {
3982
+ transform: translateY(0);
3983
+ opacity: 1;
3984
+ }
3985
+
3992
3986
  .vuiModal {
3993
3987
  display: flex;
3994
3988
  flex-direction: column;
@@ -4324,7 +4318,11 @@ h2.react-datepicker__current-month {
4324
4318
  opacity: 0;
4325
4319
  transform: translateY(-8px);
4326
4320
  transition: opacity 0.2s, transform 0.2s;
4327
- visibility: hidden;
4321
+ }
4322
+
4323
+ .vuiPopover-isLoaded {
4324
+ opacity: 1;
4325
+ transform: translateY(0);
4328
4326
  }
4329
4327
 
4330
4328
  .vuiPopover--allowOverflow {
@@ -4338,12 +4336,6 @@ h2.react-datepicker__current-month {
4338
4336
 
4339
4337
  .vuiPopover--upLeft,
4340
4338
  .vuiPopover--upRight {
4341
- transform: translateY(8px);
4342
- }
4343
-
4344
- .vuiPopover-isLoaded {
4345
- visibility: visible;
4346
- opacity: 1;
4347
4339
  transform: translateY(0);
4348
4340
  }
4349
4341
 
@@ -4367,6 +4359,10 @@ h2.react-datepicker__current-month {
4367
4359
  padding: 12px;
4368
4360
  }
4369
4361
 
4362
+ .vuiPopoverContent--paddingNone {
4363
+ padding: 0;
4364
+ }
4365
+
4370
4366
  .vuiProgressBar {
4371
4367
  position: relative;
4372
4368
  border-radius: 12px;
@@ -4496,6 +4492,14 @@ h2.react-datepicker__current-month {
4496
4492
  display: flex;
4497
4493
  align-items: center;
4498
4494
  justify-content: center;
4495
+ pointer-events: initial;
4496
+ opacity: 1;
4497
+ transition: opacity 0.2s;
4498
+ }
4499
+
4500
+ .vuiScreenBlock-isHidden {
4501
+ pointer-events: none;
4502
+ opacity: 0;
4499
4503
  }
4500
4504
 
4501
4505
  .vuiScreenBlock--default {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectara/vectara-ui",
3
- "version": "15.7.2",
3
+ "version": "15.9.0",
4
4
  "homepage": "./",
5
5
  "description": "Vectara's design system, codified as a React and Sass component library",
6
6
  "author": "Vectara",
@@ -0,0 +1,29 @@
1
+ import { useLocation } from "react-router-dom";
2
+ import { VuiTabsNavigator } from "../../../lib";
3
+
4
+ export const TabsNavigator = () => {
5
+ const { hash } = useLocation();
6
+
7
+ const routes = [
8
+ {
9
+ href: "#home",
10
+ title: "Home",
11
+ testId: "home-tab",
12
+ isActive: hash.endsWith("#home")
13
+ },
14
+ {
15
+ href: "#profile",
16
+ title: "Profile",
17
+ testId: "profile-tab",
18
+ isActive: hash.endsWith("#profile")
19
+ },
20
+ {
21
+ href: "#settings",
22
+ title: "Settings",
23
+ testId: "settings-tab",
24
+ isActive: hash.endsWith("#settings")
25
+ }
26
+ ];
27
+
28
+ return <VuiTabsNavigator routes={routes} popover={{ anchorSide: "left" }} />;
29
+ };
@@ -3,12 +3,14 @@ import { Medium } from "./Medium";
3
3
  import { FullWidth } from "./FullWidth";
4
4
  import { Links } from "./Links";
5
5
  import { Enclosed } from "./Enclosed";
6
+ import { TabsNavigator } from "./TabsNavigator";
6
7
 
7
8
  const SmallSource = require("!!raw-loader!./Small");
8
9
  const MediumSource = require("!!raw-loader!./Medium");
9
10
  const FullWidthSource = require("!!raw-loader!./FullWidth");
10
11
  const LinksSource = require("!!raw-loader!./Links");
11
12
  const EnclosedSource = require("!!raw-loader!./Enclosed");
13
+ const TabsNavigatorSource = require("!!raw-loader!./TabsNavigator");
12
14
 
13
15
  export const tabs = {
14
16
  name: "Tabs",
@@ -38,6 +40,11 @@ export const tabs = {
38
40
  name: "Enclosed",
39
41
  component: <Enclosed />,
40
42
  source: EnclosedSource.default.toString()
43
+ },
44
+ {
45
+ name: "Tabs Navigator",
46
+ component: <TabsNavigator />,
47
+ source: TabsNavigatorSource.default.toString()
41
48
  }
42
49
  ]
43
50
  };
@@ -0,0 +1,5 @@
1
+ import { VuiInfoTooltip } from "../../../lib";
2
+
3
+ export const InfoTooltip = () => {
4
+ return <VuiInfoTooltip tip="This explains a term or feature." />;
5
+ };
@@ -1,6 +1,8 @@
1
1
  import { Tooltip } from "./Tooltip";
2
+ import { InfoTooltip } from "./InfoTooltip";
2
3
 
3
4
  const TooltipSource = require("!!raw-loader!./Tooltip");
5
+ const InfoTooltipSource = require("!!raw-loader!./InfoTooltip");
4
6
 
5
7
  export const tooltip = {
6
8
  name: "Tooltip",
@@ -10,6 +12,11 @@ export const tooltip = {
10
12
  name: "Tooltip",
11
13
  component: <Tooltip />,
12
14
  source: TooltipSource.default.toString()
15
+ },
16
+ {
17
+ name: "Info Tooltip",
18
+ component: <InfoTooltip />,
19
+ source: InfoTooltipSource.default.toString()
13
20
  }
14
21
  ]
15
22
  };