@chakra-ui/tabs
Advanced tools
| export * from "./tabs" | ||
| export * from "./use-tabs" |
+292
| import { | ||
| chakra, | ||
| PropsOf, | ||
| forwardRef, | ||
| ThemingProps, | ||
| useThemeDefaultProps, | ||
| } from "@chakra-ui/system" | ||
| import { createContext, cx, __DEV__ } from "@chakra-ui/utils" | ||
| import * as React from "react" | ||
| import { | ||
| TabsContextProvider, | ||
| useTab, | ||
| useTabIndicator, | ||
| useTabList, | ||
| UseTabListProps, | ||
| useTabPanel, | ||
| useTabPanels, | ||
| UseTabProps, | ||
| useTabs, | ||
| UseTabsProps, | ||
| } from "./use-tabs" | ||
| interface TabsOptions { | ||
| /** | ||
| * If `true`, tabs will stretch to width of the tablist. | ||
| */ | ||
| isFitted?: boolean | ||
| /** | ||
| * The alignment of the tabs | ||
| */ | ||
| align?: "start" | "end" | "center" | ||
| } | ||
| interface ThemingContext extends ThemingProps, TabsOptions {} | ||
| type DivProps = Omit<PropsOf<typeof chakra.div>, "onChange"> | ||
| export type TabsProps = UseTabsProps & | ||
| DivProps & | ||
| TabsOptions & { | ||
| children: React.ReactNode | ||
| } | ||
| const [ThemingContextProvider, useThemingContext] = createContext< | ||
| ThemingContext | ||
| >({ | ||
| name: "TabsThemingContext", | ||
| }) | ||
| export { useThemingContext as useTabsThemingContext } | ||
| /** | ||
| * Tabs | ||
| * | ||
| * Provides context and logic for all tabs components. It doesn't render | ||
| * any DOM node. | ||
| */ | ||
| export const Tabs = React.forwardRef(function Tabs( | ||
| props: TabsProps, | ||
| ref: React.Ref<any>, | ||
| ) { | ||
| /** | ||
| * Gets the default props for `variant` and `size` from `theme.components.Tabs` | ||
| */ | ||
| const defaults = useThemeDefaultProps("Tabs") | ||
| const { | ||
| children, | ||
| variant = defaults?.variant, | ||
| size = defaults?.size, | ||
| colorScheme = defaults?.colorScheme, | ||
| isFitted, | ||
| className, | ||
| align = "start", | ||
| ...rest | ||
| } = props | ||
| const { htmlProps, ...context } = useTabs(rest) | ||
| const tabs = React.useMemo(() => context, [context]) | ||
| const _className = cx("chakra-tabs", className) | ||
| return ( | ||
| <TabsContextProvider value={tabs}> | ||
| <ThemingContextProvider value={{ variant, size, colorScheme, isFitted }}> | ||
| <chakra.div className={_className} ref={ref} {...htmlProps}> | ||
| {children} | ||
| </chakra.div> | ||
| </ThemingContextProvider> | ||
| </TabsContextProvider> | ||
| ) | ||
| }) | ||
| if (__DEV__) { | ||
| Tabs.displayName = "Tabs" | ||
| } | ||
| /** | ||
| * Tabs - Theming | ||
| * | ||
| * To change the styles of a tab buttons globally, update the styles in | ||
| * `theme.components.Tabs` under the `Tab` key. | ||
| */ | ||
| const StyledTab = chakra("button", { | ||
| themeKey: "Tabs.Tab", | ||
| baseStyle: { | ||
| outline: "0", | ||
| display: "flex", | ||
| alignItems: "center", | ||
| justifyContent: "center", | ||
| }, | ||
| }) | ||
| export type TabProps = Omit<UseTabProps, "context"> & PropsOf<typeof StyledTab> | ||
| /** | ||
| * Tabs | ||
| * | ||
| * The tab button used to activate a specific tab panel. It renders a `button`, | ||
| * and is responsible for automatic and manual selection modes. | ||
| */ | ||
| export const Tab = forwardRef<TabProps>(function Tab(props, ref) { | ||
| const { className, ...rest } = props | ||
| const { isFitted, ...theming } = useThemingContext() | ||
| const tabProps = useTab({ ...rest, ref }) | ||
| const _className = cx("chakra-tabs__tab", className) | ||
| return ( | ||
| <StyledTab | ||
| className={_className} | ||
| flex={isFitted ? 1 : undefined} | ||
| {...theming} | ||
| {...tabProps} | ||
| /> | ||
| ) | ||
| }) | ||
| if (__DEV__) { | ||
| Tab.displayName = "Tab" | ||
| } | ||
| /** | ||
| * TabList - Theming | ||
| * | ||
| * To change the styles of a tablist globally, update the styles in | ||
| * `theme.components.Tabs` under the `TabList` key | ||
| */ | ||
| const StyledTabList = chakra("div", { | ||
| themeKey: "Tabs.TabList", | ||
| baseStyle: { | ||
| display: "flex", | ||
| }, | ||
| }) | ||
| export type TabListProps = Omit<UseTabListProps, "context"> & | ||
| PropsOf<typeof StyledTabList> | ||
| /** | ||
| * TabList | ||
| * | ||
| * Used to manage a list of tab buttons. It renders a `div` by default, | ||
| * and is responsible the keyboard interaction between tabs. | ||
| */ | ||
| export const TabList = React.forwardRef(function TabList( | ||
| props: TabListProps, | ||
| ref: React.Ref<any>, | ||
| ) { | ||
| const { className, ...rest } = props | ||
| const { isFitted, align = "start", ...theming } = useThemingContext() | ||
| const tablistProps = useTabList({ ...rest, ref }) | ||
| const _className = cx("chakra-tabs__tablist", className) | ||
| const alignments = { | ||
| end: "flex-end", | ||
| center: "center", | ||
| start: "flex-start", | ||
| } | ||
| return ( | ||
| <StyledTabList | ||
| justifyContent={alignments[align]} | ||
| className={_className} | ||
| {...theming} | ||
| {...tablistProps} | ||
| /> | ||
| ) | ||
| }) | ||
| if (__DEV__) { | ||
| TabList.displayName = "TabList" | ||
| } | ||
| /** | ||
| * TabPanel - Theming | ||
| * | ||
| * To change the styles of tab panels globally, update the styles in | ||
| * `theme.components.Tabs` under the `TabPanel` key | ||
| */ | ||
| const StyledTabPanel = chakra("div", { | ||
| themeKey: "Tabs.TabPanel", | ||
| }) | ||
| export type TabPanelProps = PropsOf<typeof StyledTabPanel> | ||
| /** | ||
| * TabPanel | ||
| * | ||
| * Used to render the content for a specific tab. | ||
| */ | ||
| export const TabPanel = React.forwardRef(function TabPanel( | ||
| props: TabPanelProps, | ||
| ref: React.Ref<any>, | ||
| ) { | ||
| const { className, ...rest } = props | ||
| const panelProps = useTabPanel({ ...rest, ref }) | ||
| const _className = cx("chakra-tabs__tab-panel", className) | ||
| return <StyledTabPanel className={_className} {...panelProps} /> | ||
| }) | ||
| if (__DEV__) { | ||
| TabPanel.displayName = "TabPanel" | ||
| } | ||
| export type TabPanelsProps = PropsOf<typeof chakra.div> | ||
| /** | ||
| * TabPanel | ||
| * | ||
| * Used to manage the rendering of multiple tab panels. It uses | ||
| * `cloneElement` to hide/show tab panels. | ||
| * | ||
| * It renders a `div` by default. | ||
| */ | ||
| export const TabPanels = React.forwardRef(function TabPanels( | ||
| props: TabPanelsProps, | ||
| ref: React.Ref<any>, | ||
| ) { | ||
| const { className, ...rest } = props | ||
| const panelsProp = useTabPanels(rest) | ||
| const _className = cx("chakra-tabs__tab-panels", className) | ||
| return <chakra.div ref={ref} className={_className} {...panelsProp} /> | ||
| }) | ||
| if (__DEV__) { | ||
| TabPanels.displayName = "TabPanels" | ||
| } | ||
| /** | ||
| * TabIndicator - Theming | ||
| * | ||
| * To change the styles of tab indicator globally, update the styles in | ||
| * `theme.components.Tabs` under the `TabIndicator` key | ||
| */ | ||
| const StyledTabIndicator = chakra("div", { | ||
| themeKey: "Tabs.TabIndicator", | ||
| }) | ||
| export type TabIndicatorProps = PropsOf<typeof chakra.div> | ||
| /** | ||
| * TabIndicator | ||
| * | ||
| * Used to render an active tab indicator that animates between | ||
| * selected tabs. | ||
| */ | ||
| export const TabIndicator = React.forwardRef(function TabIndicator( | ||
| props: TabIndicatorProps, | ||
| ref: React.Ref<any>, | ||
| ) { | ||
| const { className, style, ...rest } = props | ||
| const styles = useTabIndicator() | ||
| const _className = cx("chakra-tabs__tab-indicator", className) | ||
| const _style = { ...style, ...styles } | ||
| return ( | ||
| <StyledTabIndicator | ||
| ref={ref} | ||
| className={_className} | ||
| style={_style} | ||
| {...rest} | ||
| /> | ||
| ) | ||
| }) | ||
| if (__DEV__) { | ||
| TabIndicator.displayName = "TabIndicator" | ||
| } |
+442
| import { useClickable, UseClickableProps } from "@chakra-ui/clickable" | ||
| import { useDescendant, useDescendants } from "@chakra-ui/descendant" | ||
| import { | ||
| useControllableState, | ||
| useId, | ||
| useSafeLayoutEffect, | ||
| } from "@chakra-ui/hooks" | ||
| import { | ||
| callAllHandlers, | ||
| createOnKeyDown, | ||
| Dict, | ||
| getValidChildren, | ||
| isUndefined, | ||
| mergeRefs, | ||
| createContext, | ||
| } from "@chakra-ui/utils" | ||
| import * as React from "react" | ||
| export interface UseTabsProps { | ||
| /** | ||
| * The orientation of the tab list. | ||
| */ | ||
| orientation?: "vertical" | "horizontal" | ||
| /** | ||
| * If `true`, the tabs will be manually activated and | ||
| * display its panel by pressing Space or Enter. | ||
| * | ||
| * If `false`, the tabs will be automatically activated | ||
| * and their panel is displayed when they receive focus. | ||
| */ | ||
| isManual?: boolean | ||
| /** | ||
| * Callback when the index (controlled or un-controlled) changes. | ||
| */ | ||
| onChange?: (index: number) => void | ||
| /** | ||
| * The index of the selected tab (in controlled mode) | ||
| */ | ||
| index?: number | ||
| /** | ||
| * The initial index of the selected tab (in uncontrolled mode) | ||
| */ | ||
| defaultIndex?: number | ||
| /** | ||
| * The id of the tab | ||
| */ | ||
| id?: string | ||
| } | ||
| /** | ||
| * Tabs hooks that provides all the states, and accessibility | ||
| * helpers to keep all things working properly. | ||
| * | ||
| * It's returned object will be passed unto a Context Provider | ||
| * so all child components can read from it. | ||
| * | ||
| * @see Docs https://chakra-ui.com/components/useTabs | ||
| */ | ||
| export function useTabs(props: UseTabsProps) { | ||
| const { | ||
| defaultIndex, | ||
| onChange, | ||
| index, | ||
| isManual, | ||
| orientation = "horizontal", | ||
| ...htmlProps | ||
| } = props | ||
| /** | ||
| * We use this to keep track of the index of the focused tab. | ||
| * | ||
| * Tabs can be automatically activated, this means selection follows focus. | ||
| * When we navigate with the arrow keys, we move focus and selection to next/prev tab | ||
| * | ||
| * Tabs can also be manually activated, this means selection does not follow focus. | ||
| * When we navigate with the arrow keys, we only move focus NOT selection. The user | ||
| * will need not manually activate the tab using `Enter` or `Space`. | ||
| * | ||
| * This is why we need to keep track of the `focusedIndex` and `selectedIndex` | ||
| */ | ||
| const [focusedIndex, setFocusedIndex] = React.useState(defaultIndex ?? 0) | ||
| const [selectedIndex, setSelectedIndex] = useControllableState({ | ||
| defaultValue: defaultIndex ?? 0, | ||
| value: index, | ||
| onChange, | ||
| shouldUpdate: (prevIndex, nextIndex) => prevIndex !== nextIndex, | ||
| propsMap: { | ||
| value: "index", | ||
| defaultValue: "defaultIndex", | ||
| }, | ||
| }) | ||
| /** | ||
| * Sync focused `index` with controlled `selectedIndex` (which is the `props.index`) | ||
| */ | ||
| React.useEffect(() => { | ||
| if (!isUndefined(index)) { | ||
| setFocusedIndex(index) | ||
| } | ||
| }, [index]) | ||
| /** | ||
| * Think of `useDescendants` as a register for the tab nodes. | ||
| * | ||
| * This manager is used to store only the tab nodes that are not disabled, and focusable. | ||
| * If we have the following code | ||
| * | ||
| * ```jsx | ||
| * <Tab>Tab 1</Tab> | ||
| * <Tab isDisabled>Tab 2</Tab> | ||
| * <Tab>Tab 3</Tab> | ||
| * ``` | ||
| * | ||
| * The manager will only hold references to "Tab 1" and "Tab 3", since `Tab 2` is disabled | ||
| */ | ||
| const enabledDomContext = useDescendants() | ||
| /** | ||
| * This manager is used to store all tab nodes whether disabled or not. | ||
| * If we have the following code | ||
| * | ||
| * ```jsx | ||
| * <Tab>Tab 1</Tab> | ||
| * <Tab isDisabled>Tab 2</Tab> | ||
| * <Tab>Tab 3</Tab> | ||
| * ``` | ||
| * | ||
| * The manager will only hold references to "Tab 1", "Tab 2" "Tab 3". | ||
| * | ||
| * We need this for correct indexing of tabs in event a tab is disabled | ||
| */ | ||
| const domContext = useDescendants() | ||
| /** | ||
| * generate a unique id or use user-provided id for | ||
| * the tabs widget | ||
| */ | ||
| const id = useId(props.id, `tabs`) | ||
| return { | ||
| id, | ||
| selectedIndex, | ||
| focusedIndex, | ||
| setSelectedIndex, | ||
| setFocusedIndex, | ||
| isManual, | ||
| orientation, | ||
| enabledDomContext, | ||
| domContext, | ||
| htmlProps, | ||
| } | ||
| } | ||
| export type UseTabsReturn = Omit<ReturnType<typeof useTabs>, "htmlProps"> | ||
| const [TabsContextProvider, useTabsContext] = createContext<UseTabsReturn>({ | ||
| strict: true, | ||
| name: "TabsContext", | ||
| errorMessage: | ||
| "Chakra UI: useTabsContext can only be used within TabsContextProvider", | ||
| }) | ||
| export { TabsContextProvider } | ||
| type Child = React.ReactElement<any> | ||
| export interface UseTabListProps { | ||
| children?: React.ReactNode | ||
| onKeyDown?: React.KeyboardEventHandler | ||
| ref?: React.Ref<any> | ||
| } | ||
| /** | ||
| * Tabs hook to manage multiple tab buttons, | ||
| * and ensures only one tab is selected per time. | ||
| * | ||
| * @param props props object for the tablist | ||
| */ | ||
| export function useTabList<P extends UseTabListProps>(props: P) { | ||
| const { | ||
| setFocusedIndex, | ||
| focusedIndex, | ||
| orientation, | ||
| enabledDomContext, | ||
| } = useTabsContext() | ||
| const count = enabledDomContext.descendants.length | ||
| /** | ||
| * Function to update the selected tab index | ||
| */ | ||
| const setIndex = (index: number) => { | ||
| const tab = enabledDomContext.descendants[index] | ||
| if (tab?.element) { | ||
| tab.element.focus() | ||
| setFocusedIndex(index) | ||
| } | ||
| } | ||
| // Helper functions for keyboard navigation | ||
| const nextTab = () => { | ||
| const nextIndex = (focusedIndex + 1) % count | ||
| setIndex(nextIndex) | ||
| } | ||
| const prevTab = () => { | ||
| const prevIndex = (focusedIndex - 1 + count) % count | ||
| setIndex(prevIndex) | ||
| } | ||
| const firstTab = () => setIndex(0) | ||
| const lastTab = () => setIndex(count - 1) | ||
| const isHorizontal = orientation === "horizontal" | ||
| const isVertical = orientation === "vertical" | ||
| const onKeyDown = createOnKeyDown({ | ||
| keyMap: { | ||
| ArrowRight: () => isHorizontal && nextTab(), | ||
| ArrowLeft: () => isHorizontal && prevTab(), | ||
| ArrowDown: () => isVertical && nextTab(), | ||
| ArrowUp: () => isVertical && prevTab(), | ||
| Home: () => firstTab(), | ||
| End: () => lastTab(), | ||
| }, | ||
| }) | ||
| return { | ||
| ...props, | ||
| role: "tablist", | ||
| "aria-orientation": orientation, | ||
| onKeyDown: callAllHandlers(props.onKeyDown, onKeyDown), | ||
| } | ||
| } | ||
| export type UseTabListReturn = ReturnType<typeof useTabList> | ||
| export interface UseTabProps extends UseClickableProps { | ||
| id?: string | ||
| isSelected?: boolean | ||
| panelId?: string | ||
| onFocus?: React.FocusEventHandler | ||
| } | ||
| /** | ||
| * Tabs hook to manage each tab button. | ||
| * | ||
| * A tab can be disabled and focusable, or both, | ||
| * hence the use of `useClickable` to handle this scenario | ||
| */ | ||
| export function useTab<P extends UseTabProps>( | ||
| props: P, | ||
| ): React.ButtonHTMLAttributes<any> { | ||
| const { isDisabled, isFocusable, ...htmlProps } = props | ||
| const { | ||
| setSelectedIndex, | ||
| isManual, | ||
| id, | ||
| setFocusedIndex, | ||
| enabledDomContext, | ||
| domContext, | ||
| selectedIndex, | ||
| } = useTabsContext() | ||
| const ref = React.useRef<HTMLElement>(null) | ||
| /** | ||
| * Think of `useDescendant` as the function that registers tab node | ||
| * to the `enabledDomContext`, and returns it's index. | ||
| * | ||
| * Tab is registered if it's enabled or focusable | ||
| */ | ||
| const enabledIndex = useDescendant({ | ||
| disabled: Boolean(isDisabled), | ||
| focusable: Boolean(isFocusable), | ||
| context: enabledDomContext, | ||
| element: ref.current, | ||
| }) | ||
| /** | ||
| * Registers all tabs (whether disabled or not) | ||
| */ | ||
| const index = useDescendant({ | ||
| context: domContext, | ||
| element: ref.current, | ||
| }) | ||
| const isSelected = index === selectedIndex | ||
| const onClick = () => { | ||
| setFocusedIndex(enabledIndex) | ||
| setSelectedIndex(index) | ||
| } | ||
| const onFocus = () => { | ||
| const isDisabledButFocusable = isDisabled && isFocusable | ||
| const shouldSelect = !isManual && !isDisabledButFocusable | ||
| if (shouldSelect) { | ||
| setSelectedIndex(index) | ||
| } | ||
| } | ||
| const clickable = useClickable({ | ||
| ...htmlProps, | ||
| ref: mergeRefs(ref, props.ref), | ||
| isDisabled, | ||
| isFocusable, | ||
| onClick: callAllHandlers(props.onClick, onClick), | ||
| }) | ||
| const type: "button" | "submit" | "reset" = "button" | ||
| return { | ||
| ...clickable, | ||
| id: makeTabId(id, index), | ||
| role: "tab", | ||
| tabIndex: isSelected ? 0 : -1, | ||
| type, | ||
| "aria-selected": isSelected ? true : undefined, | ||
| "aria-controls": makeTabPanelId(id, index), | ||
| onFocus: callAllHandlers(props.onFocus, onFocus), | ||
| } | ||
| } | ||
| export interface UseTabPanelsProps { | ||
| children?: React.ReactNode | ||
| } | ||
| /** | ||
| * Tabs hook for managing the visibility of multiple tab panels. | ||
| * | ||
| * Since only one panel can be show at a time, we use `React.cloneElement` | ||
| * to inject `selected` panel to each TabPanel. | ||
| * | ||
| * It returns a cloned version of it's children with | ||
| * all functionality included. | ||
| */ | ||
| export function useTabPanels<P extends UseTabPanelsProps>(props: P) { | ||
| const context = useTabsContext() | ||
| const { id, selectedIndex } = context | ||
| const validChildren = getValidChildren(props.children) | ||
| const children = validChildren.map((child, index) => | ||
| React.cloneElement(child as Child, { | ||
| isSelected: index === selectedIndex, | ||
| id: makeTabPanelId(id, index), | ||
| }), | ||
| ) | ||
| return { ...props, children } | ||
| } | ||
| /** | ||
| * Tabs hook for managing the visible/hidden states | ||
| * of the tab panel. | ||
| * | ||
| * @param props props object for the tab panel | ||
| */ | ||
| export function useTabPanel(props: Dict) { | ||
| const { isSelected, id, ...htmlProps } = props | ||
| return { | ||
| ...htmlProps, | ||
| role: "tabpanel", | ||
| hidden: !isSelected, | ||
| id, | ||
| } | ||
| } | ||
| /** | ||
| * Tabs hook to show an animated indicators that | ||
| * follows the active tab. | ||
| * | ||
| * The way we do it is by measuring the DOM Rect (or dimensions) | ||
| * of the active tab, and return that as CSS style for | ||
| * the indicator. | ||
| */ | ||
| export function useTabIndicator(): React.CSSProperties { | ||
| const context = useTabsContext() | ||
| const { selectedIndex, orientation, domContext } = context | ||
| const isHorizontal = orientation === "horizontal" | ||
| const isVertical = orientation === "vertical" | ||
| // Get the clientRect of the selected tab | ||
| const [rect, setRect] = React.useState(() => { | ||
| if (isHorizontal) return { left: 0, width: 0 } | ||
| if (isVertical) return { top: 0, height: 0 } | ||
| }) | ||
| const [hasMeasured, setHasMeasured] = React.useState(false) | ||
| // Update the selected tab rect when the selectedIndex changes | ||
| useSafeLayoutEffect(() => { | ||
| if (isUndefined(selectedIndex)) return | ||
| const tab = domContext.descendants[selectedIndex] | ||
| const tabRect = tab?.element?.getBoundingClientRect() | ||
| // Horizontal Tab: Calculate width and left distance | ||
| if (isHorizontal && tabRect) { | ||
| const { left, width } = tabRect | ||
| setRect({ left, width }) | ||
| } | ||
| // Vertical Tab: Calculate height and top distance | ||
| if (isVertical && tabRect) { | ||
| const { top, height } = tabRect | ||
| setRect({ top, height }) | ||
| } | ||
| // Prevent unwanted transition from 0 to measured rect | ||
| // by setting the measured state in the next tick | ||
| const frameId = requestAnimationFrame(() => { | ||
| setHasMeasured(true) | ||
| }) | ||
| return () => { | ||
| cancelAnimationFrame(frameId) | ||
| } | ||
| }, [selectedIndex, isHorizontal, isVertical, domContext.descendants]) | ||
| return { | ||
| position: "absolute", | ||
| transition: hasMeasured ? "all 200ms cubic-bezier(0, 0, 0.2, 1)" : "none", | ||
| ...rect, | ||
| } | ||
| } | ||
| function makeTabId(id: string, index: number) { | ||
| return `${id}--tab-${index}` | ||
| } | ||
| function makeTabPanelId(id: string, index: number) { | ||
| return `${id}--tabpanel-${index}` | ||
| } |
+10
-13
| # Change Log | ||
| All notable changes to this project will be documented in this file. | ||
| See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. | ||
| All notable changes to this project will be documented in this file. See | ||
| [Conventional Commits](https://conventionalcommits.org) for commit guidelines. | ||
| # 1.0.0-next.2 (2020-06-22) | ||
| # 1.0.0-next.3 (2020-06-28) | ||
| ### Bug Fixes | ||
| * [#891](https://github.com/chakra-ui/chakra-ui/issues/891) ([e107acc](https://github.com/chakra-ui/chakra-ui/commit/e107acc8487898a965b0d695c1da71f46fc56d5e)) | ||
| * ts issue with sx prop ([d3b1340](https://github.com/chakra-ui/chakra-ui/commit/d3b1340cb255937927b4d4c56ce218141570b951)) | ||
| - [#891](https://github.com/chakra-ui/chakra-ui/issues/891) | ||
| ([e107acc](https://github.com/chakra-ui/chakra-ui/commit/e107acc8487898a965b0d695c1da71f46fc56d5e)) | ||
| - ts issue with sx prop | ||
| ([d3b1340](https://github.com/chakra-ui/chakra-ui/commit/d3b1340cb255937927b4d4c56ce218141570b951)) | ||
| ### Features | ||
| * support global tab indicator styling ([548f975](https://github.com/chakra-ui/chakra-ui/commit/548f9753e730f377aa2324ebf603a88c0152650e)) | ||
| - support global tab indicator styling | ||
| ([548f975](https://github.com/chakra-ui/chakra-ui/commit/548f9753e730f377aa2324ebf603a88c0152650e)) | ||
| # Change Log | ||
@@ -28,3 +25,3 @@ | ||
| # 1.0.0-next.1 (2020-06-21) | ||
| # 1.0.0-next.2 (2020-06-21) | ||
@@ -31,0 +28,0 @@ ### Bug Fixes |
+26
-13
@@ -51,3 +51,5 @@ "use strict"; | ||
| className = props.className, | ||
| rest = _objectWithoutPropertiesLoose(props, ["children", "variant", "size", "colorScheme", "isFitted", "className"]); | ||
| _props$align = props.align, | ||
| align = _props$align === void 0 ? "start" : _props$align, | ||
| rest = _objectWithoutPropertiesLoose(props, ["children", "variant", "size", "colorScheme", "isFitted", "className", "align"]); | ||
@@ -109,3 +111,3 @@ var _useTabs = (0, _useTabs2.useTabs)(rest), | ||
| var className = props.className, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
@@ -116,3 +118,3 @@ var _useThemingContext = useThemingContext(), | ||
| var tabProps = (0, _useTabs2.useTab)(_extends({}, htmlProps, { | ||
| var tabProps = (0, _useTabs2.useTab)(_extends({}, rest, { | ||
| ref: ref | ||
@@ -142,3 +144,6 @@ })); | ||
| var StyledTabList = (0, _system.chakra)("div", { | ||
| themeKey: "Tabs.TabList" | ||
| themeKey: "Tabs.TabList", | ||
| baseStyle: { | ||
| display: "flex" | ||
| } | ||
| }); | ||
@@ -154,9 +159,11 @@ | ||
| var className = props.className, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var _useThemingContext2 = useThemingContext(), | ||
| isFitted = _useThemingContext2.isFitted, | ||
| theming = _objectWithoutPropertiesLoose(_useThemingContext2, ["isFitted"]); | ||
| _useThemingContext2$a = _useThemingContext2.align, | ||
| align = _useThemingContext2$a === void 0 ? "start" : _useThemingContext2$a, | ||
| theming = _objectWithoutPropertiesLoose(_useThemingContext2, ["isFitted", "align"]); | ||
| var tablistProps = (0, _useTabs2.useTabList)(_extends({}, htmlProps, { | ||
| var tablistProps = (0, _useTabs2.useTabList)(_extends({}, rest, { | ||
| ref: ref | ||
@@ -167,3 +174,9 @@ })); | ||
| var alignments = { | ||
| end: "flex-end", | ||
| center: "center", | ||
| start: "flex-start" | ||
| }; | ||
| return /*#__PURE__*/React.createElement(StyledTabList, _extends({ | ||
| justifyContent: alignments[align], | ||
| className: _className | ||
@@ -196,5 +209,5 @@ }, theming, tablistProps)); | ||
| var className = props.className, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var panelProps = (0, _useTabs2.useTabPanel)(_extends({}, htmlProps, { | ||
| var panelProps = (0, _useTabs2.useTabPanel)(_extends({}, rest, { | ||
| ref: ref | ||
@@ -225,5 +238,5 @@ })); | ||
| var className = props.className, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var panelsProp = (0, _useTabs2.useTabPanels)(htmlProps); | ||
| var panelsProp = (0, _useTabs2.useTabPanels)(rest); | ||
@@ -263,3 +276,3 @@ var _className = (0, _utils.cx)("chakra-tabs__tab-panels", className); | ||
| style = props.style, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className", "style"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className", "style"]); | ||
@@ -276,3 +289,3 @@ var styles = (0, _useTabs2.useTabIndicator)(); | ||
| style: _style | ||
| }, htmlProps)); | ||
| }, rest)); | ||
| }); | ||
@@ -279,0 +292,0 @@ exports.TabIndicator = TabIndicator; |
+27
-14
@@ -32,5 +32,6 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
| isFitted, | ||
| className | ||
| className, | ||
| align = "start" | ||
| } = props, | ||
| rest = _objectWithoutPropertiesLoose(props, ["children", "variant", "size", "colorScheme", "isFitted", "className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["children", "variant", "size", "colorScheme", "isFitted", "className", "align"]); | ||
@@ -93,3 +94,3 @@ var _useTabs = useTabs(rest), | ||
| } = props, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
@@ -102,3 +103,3 @@ var _useThemingContext = useThemingContext(), | ||
| var tabProps = useTab(_extends({}, htmlProps, { | ||
| var tabProps = useTab(_extends({}, rest, { | ||
| ref | ||
@@ -127,3 +128,6 @@ })); | ||
| var StyledTabList = chakra("div", { | ||
| themeKey: "Tabs.TabList" | ||
| themeKey: "Tabs.TabList", | ||
| baseStyle: { | ||
| display: "flex" | ||
| } | ||
| }); | ||
@@ -141,8 +145,11 @@ | ||
| } = props, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var _useThemingContext2 = useThemingContext(), | ||
| theming = _objectWithoutPropertiesLoose(_useThemingContext2, ["isFitted"]); | ||
| { | ||
| align = "start" | ||
| } = _useThemingContext2, | ||
| theming = _objectWithoutPropertiesLoose(_useThemingContext2, ["isFitted", "align"]); | ||
| var tablistProps = useTabList(_extends({}, htmlProps, { | ||
| var tablistProps = useTabList(_extends({}, rest, { | ||
| ref | ||
@@ -153,3 +160,9 @@ })); | ||
| var alignments = { | ||
| end: "flex-end", | ||
| center: "center", | ||
| start: "flex-start" | ||
| }; | ||
| return /*#__PURE__*/React.createElement(StyledTabList, _extends({ | ||
| justifyContent: alignments[align], | ||
| className: _className | ||
@@ -183,5 +196,5 @@ }, theming, tablistProps)); | ||
| } = props, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var panelProps = useTabPanel(_extends({}, htmlProps, { | ||
| var panelProps = useTabPanel(_extends({}, rest, { | ||
| ref | ||
@@ -213,5 +226,5 @@ })); | ||
| } = props, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className"]); | ||
| var panelsProp = useTabPanels(htmlProps); | ||
| var panelsProp = useTabPanels(rest); | ||
@@ -252,3 +265,3 @@ var _className = cx("chakra-tabs__tab-panels", className); | ||
| } = props, | ||
| htmlProps = _objectWithoutPropertiesLoose(props, ["className", "style"]); | ||
| rest = _objectWithoutPropertiesLoose(props, ["className", "style"]); | ||
@@ -265,3 +278,3 @@ var styles = useTabIndicator(); | ||
| style: _style | ||
| }, htmlProps)); | ||
| }, rest)); | ||
| }); | ||
@@ -268,0 +281,0 @@ |
+10
-8
| { | ||
| "name": "@chakra-ui/tabs", | ||
| "version": "1.0.0-next.2", | ||
| "version": "1.0.0-next.3", | ||
| "description": "Accessible Tabs component for React and Chakra UI", | ||
@@ -22,2 +22,3 @@ "keywords": [ | ||
| ], | ||
| "sideEffects": false, | ||
| "author": "Segun Adebayo <sage@adebayosegun.com>", | ||
@@ -31,3 +32,4 @@ "homepage": "https://github.com/chakra-ui/chakra-ui#readme", | ||
| "files": [ | ||
| "dist" | ||
| "dist", | ||
| "src" | ||
| ], | ||
@@ -59,9 +61,9 @@ "publishConfig": { | ||
| "dependencies": { | ||
| "@chakra-ui/clickable": "^1.0.0-next.2", | ||
| "@chakra-ui/descendant": "^1.0.0-next.2", | ||
| "@chakra-ui/hooks": "^1.0.0-next.2", | ||
| "@chakra-ui/utils": "^1.0.0-next.2" | ||
| "@chakra-ui/clickable": "^1.0.0-next.3", | ||
| "@chakra-ui/descendant": "^1.0.0-next.3", | ||
| "@chakra-ui/hooks": "^1.0.0-next.3", | ||
| "@chakra-ui/utils": "^1.0.0-next.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@chakra-ui/system": "^1.0.0-next.2" | ||
| "@chakra-ui/system": "^1.0.0-next.3" | ||
| }, | ||
@@ -72,3 +74,3 @@ "peerDependencies": { | ||
| }, | ||
| "gitHead": "c5b51e43e9dff400f8bba7da7ffd135f5d33628b" | ||
| "gitHead": "d31ba9c35993985f49da4885dd47ab8dab49cdd1" | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
241842
8.85%25
13.64%2477
36.7%8
33.33%