mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-24 11:26:31 +00:00
Merge remote-tracking branch 'origin/main' into conico/rnd-9299-fallback-computed
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Align styling of PageLinkItem and PageDocumentItem
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Better conditional display of page actions
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Standardise toggle chevrons across the app
|
||||
@@ -273,10 +273,10 @@ const testCases: TestsCase[] = [
|
||||
await expect(navigationLink).not.toBeVisible();
|
||||
|
||||
// Find and click the chevron element that is next to "Editor" in the TOC
|
||||
// It is a span inside the link
|
||||
// It is a button inside the link
|
||||
const editorChevron = page
|
||||
.getByRole('link', { name: 'Editor' })
|
||||
.locator('span');
|
||||
.locator('button');
|
||||
await editorChevron.click();
|
||||
|
||||
// Verify "Navigation" link becomes visible after expansion
|
||||
@@ -295,10 +295,10 @@ const testCases: TestsCase[] = [
|
||||
await expect(navigationLink).not.toBeVisible();
|
||||
|
||||
// Find and click the chevron element that is next to "Editor" in the TOC
|
||||
// It is a span inside the link
|
||||
// It is a button inside the link
|
||||
const editorChevron = page
|
||||
.getByRole('link', { name: 'Editor' })
|
||||
.locator('span');
|
||||
.locator('button');
|
||||
await editorChevron.click();
|
||||
|
||||
// At this stage the link should still not be visible
|
||||
@@ -307,7 +307,7 @@ const testCases: TestsCase[] = [
|
||||
// Then we click 'Content Structure' chevron to expand further
|
||||
const contentStructureChevron = page
|
||||
.getByRole('link', { name: 'Content Structure' })
|
||||
.locator('span');
|
||||
.locator('button');
|
||||
await contentStructureChevron.click();
|
||||
|
||||
// Verify "Spaces" link becomes visible after expansion
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useEffect, useId, useMemo, useRef, useState } from 'react';
|
||||
import { useAdaptiveVisitor } from '@/components/Adaptive';
|
||||
import { useInViewportListener } from '@/components/hooks/useInViewportListener';
|
||||
import { useScrollListener } from '@/components/hooks/useScrollListener';
|
||||
import { Button } from '@/components/primitives';
|
||||
import { Button, ToggleChevron } from '@/components/primitives';
|
||||
import { t, useLanguage } from '@/intl/client';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import { useDebounceCallback } from 'usehooks-ts';
|
||||
@@ -183,7 +183,7 @@ function CodeBlockExpandable(props: {
|
||||
</div>
|
||||
<div className="pointer-events-none absolute bottom-0 flex w-full justify-center">
|
||||
<Button
|
||||
icon={isExpanded ? 'chevron-up' : 'chevron-down'}
|
||||
icon={<ToggleChevron open={isExpanded} />}
|
||||
size="xsmall"
|
||||
variant="blank"
|
||||
type="button"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Icon } from '@gitbook/icons';
|
||||
import { getNodeFragmentByType } from '@/lib/document';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { ToggleChevron } from '@/components/primitives';
|
||||
import type { BlockProps } from '../Block';
|
||||
import { Blocks } from '../Blocks';
|
||||
import { Inlines } from '../Inlines';
|
||||
@@ -46,14 +47,14 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
|
||||
'[&::-webkit-details-marker]:hidden'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon="chevron-right"
|
||||
<ToggleChevron
|
||||
orientation="right-to-down"
|
||||
open={context.mode === 'print'}
|
||||
className={tcls(
|
||||
'inline-block',
|
||||
'size-3',
|
||||
'mr-3',
|
||||
'mb-1',
|
||||
'transition-transform',
|
||||
'shrink-0',
|
||||
'group-open/expandable:rotate-90'
|
||||
)}
|
||||
|
||||
@@ -11,10 +11,9 @@ import assertNever from 'assert-never';
|
||||
import { resolveContentRef } from '@/lib/references';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { Button, Link } from '../primitives';
|
||||
import { Button, Link, ToggleChevron } from '../primitives';
|
||||
import {
|
||||
type DropdownButtonProps,
|
||||
DropdownChevron,
|
||||
DropdownMenu,
|
||||
DropdownMenuItem,
|
||||
} from '../primitives/DropdownMenu';
|
||||
@@ -177,7 +176,7 @@ function HeaderItemLink(props: Omit<HeaderLinkNavItemProps, 'linkStyle'>) {
|
||||
{...rest}
|
||||
>
|
||||
{title}
|
||||
{isDropdown ? <DropdownChevron /> : null}
|
||||
{isDropdown ? <ToggleChevron /> : null}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
@@ -195,7 +194,7 @@ function HeaderItemDropdown(
|
||||
{...rest}
|
||||
>
|
||||
{title}
|
||||
<DropdownChevron />
|
||||
<ToggleChevron />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,8 @@ import type React from 'react';
|
||||
import { resolveContentRef } from '@/lib/references';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import {
|
||||
DropdownChevron,
|
||||
DropdownMenu,
|
||||
DropdownMenuItem,
|
||||
DropdownSubMenu,
|
||||
} from '../primitives/DropdownMenu';
|
||||
import { ToggleChevron } from '../primitives';
|
||||
import { DropdownMenu, DropdownMenuItem, DropdownSubMenu } from '../primitives/DropdownMenu';
|
||||
import styles from './headerLinks.module.css';
|
||||
|
||||
/**
|
||||
@@ -44,7 +40,7 @@ export function HeaderLinkMore(props: {
|
||||
>
|
||||
<span className="sr-only">{label}</span>
|
||||
<Icon icon="ellipsis" className={tcls('size-4')} />
|
||||
<DropdownChevron />
|
||||
<ToggleChevron />
|
||||
</button>
|
||||
);
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import { useMemo } from 'react';
|
||||
import type { GitBookSiteContext } from '@/lib/context';
|
||||
import { getSiteSpaceURL } from '@/lib/sites';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import { Button, type ButtonProps } from '../primitives';
|
||||
import { DropdownChevron, DropdownMenu } from '../primitives/DropdownMenu';
|
||||
import { Button, type ButtonProps, ToggleChevron } from '../primitives';
|
||||
import { DropdownMenu } from '../primitives/DropdownMenu';
|
||||
import { SpacesDropdownMenuItems } from './SpacesDropdownMenuItem';
|
||||
|
||||
// Memoized regex for checking if a string starts with an emoji
|
||||
@@ -37,7 +37,7 @@ export function SpacesDropdown(props: {
|
||||
data-testid="space-dropdown-button"
|
||||
size="small"
|
||||
variant={variant}
|
||||
trailing={<DropdownChevron />}
|
||||
trailing={<ToggleChevron />}
|
||||
className={tcls('bg-tint-base', className)}
|
||||
>
|
||||
<span className="button-content">{siteSpace.title}</span>
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Button, ButtonGroup } from '@/components/primitives/Button';
|
||||
import { DropdownMenu, DropdownMenuSeparator } from '@/components/primitives/DropdownMenu';
|
||||
import { tString, useLanguage } from '@/intl/client';
|
||||
import type { GitSyncState, SiteCustomizationSettings } from '@gitbook/api';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import React, { useRef } from 'react';
|
||||
import { useAI } from '../AI';
|
||||
import { ToggleChevron } from '../primitives';
|
||||
import {
|
||||
ActionCopyMCPURL,
|
||||
ActionCopyMarkdown,
|
||||
@@ -51,18 +51,13 @@ export function PageActionsDropdown(props: PageActionsDropdownProps) {
|
||||
return defaultAction || dropdownActions.length > 0 ? (
|
||||
<ButtonGroup ref={ref} className={props.className}>
|
||||
{defaultAction}
|
||||
{dropdownActions.length > 0 ? (
|
||||
{!defaultAction || dropdownActions.length > 1 ? (
|
||||
<DropdownMenu
|
||||
align="end"
|
||||
className="!min-w-60 max-w-max"
|
||||
button={
|
||||
<Button
|
||||
icon={
|
||||
<Icon
|
||||
icon="chevron-down"
|
||||
className="size-text-sm transition-transform group-data-[state=open]/button:rotate-180"
|
||||
/>
|
||||
}
|
||||
icon={<ToggleChevron className="size-text-sm" />}
|
||||
label={tString(language, defaultAction ? 'more' : 'actions')}
|
||||
iconOnly={!!defaultAction}
|
||||
size="xsmall"
|
||||
|
||||
@@ -28,6 +28,14 @@ export async function PageHeader(props: {
|
||||
|
||||
const hasAncestors = ancestors.length > 0;
|
||||
|
||||
// Show page actions if *any* of the actions are enabled
|
||||
const hasPageActions = [
|
||||
...Object.values(context.customization.pageActions),
|
||||
context.customization.pdf.enabled,
|
||||
context.customization.git.showEditLink,
|
||||
withRSSFeed,
|
||||
].some(Boolean);
|
||||
|
||||
return (
|
||||
<header
|
||||
className={tcls(
|
||||
@@ -41,8 +49,7 @@ export async function PageHeader(props: {
|
||||
hasAncestors ? 'page-has-ancestors' : 'page-no-ancestors'
|
||||
)}
|
||||
>
|
||||
{page.layout.tableOfContents ? (
|
||||
// Show page actions if *any* of the actions are enabled
|
||||
{page.layout.tableOfContents && hasPageActions ? (
|
||||
<PageActionsDropdown
|
||||
siteTitle={context.site.title}
|
||||
urls={getPageActionsURLs({ context, page, withRSSFeed })}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { t, tString, useLanguage } from '@/intl/client';
|
||||
import type { SiteSection } from '@gitbook/api';
|
||||
import { Button, DropdownChevron, DropdownMenu, DropdownMenuItem } from '../primitives';
|
||||
import { Button, DropdownMenu, DropdownMenuItem, ToggleChevron } from '../primitives';
|
||||
import { useSearch } from './useSearch';
|
||||
|
||||
interface SearchScopeControlProps {
|
||||
@@ -64,7 +64,7 @@ function SearchScopeSectionControl(props: SearchScopeControlProps & { isExtended
|
||||
isExtended ? 'search_scope_section_all' : 'search_scope_section_current',
|
||||
section?.title ?? ''
|
||||
)}
|
||||
trailing={<DropdownChevron />}
|
||||
trailing={<ToggleChevron />}
|
||||
/>
|
||||
}
|
||||
>
|
||||
@@ -123,7 +123,7 @@ function SearchScopeVariantControl(props: SearchScopeControlProps & { isExtended
|
||||
isExtended ? 'search_scope_variant_all' : 'search_scope_variant_current',
|
||||
spaceTitle ?? ''
|
||||
)}
|
||||
trailing={<DropdownChevron />}
|
||||
trailing={<ToggleChevron />}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use client';
|
||||
|
||||
import { Icon, type IconName } from '@gitbook/icons';
|
||||
import type { IconName } from '@gitbook/icons';
|
||||
import { motion } from 'motion/react';
|
||||
import React from 'react';
|
||||
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
import { findSectionInGroup } from '@/lib/utils';
|
||||
import { useToggleAnimation } from '../hooks';
|
||||
import { Link } from '../primitives';
|
||||
import { Link, ToggleChevron } from '../primitives';
|
||||
import { ScrollContainer } from '../primitives/ScrollContainer';
|
||||
import { SectionIcon } from './SectionIcon';
|
||||
import type {
|
||||
@@ -199,21 +199,18 @@ export function SiteSectionGroupItem(props: {
|
||||
isActiveGroup && 'hover:bg-tint-hover'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon="chevron-right"
|
||||
<ToggleChevron
|
||||
open={isOpen}
|
||||
orientation="right-to-down"
|
||||
className={tcls(
|
||||
'grid',
|
||||
'shrink-0',
|
||||
'size-3',
|
||||
'm-1',
|
||||
'transition-opacity',
|
||||
'text-current',
|
||||
'transition-transform',
|
||||
'opacity-6',
|
||||
'group-hover:opacity-11',
|
||||
'contrast-more:opacity-11',
|
||||
|
||||
isOpen ? 'rotate-90' : 'rotate-0'
|
||||
'contrast-more:opacity-11'
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { IconName } from '@gitbook/icons';
|
||||
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
|
||||
import React from 'react';
|
||||
|
||||
import { Button, DropdownChevron, Link } from '@/components/primitives';
|
||||
import { Button, Link, ToggleChevron } from '@/components/primitives';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import { findSectionInGroup } from '@/lib/utils';
|
||||
import { useIsMobile } from '../hooks/useIsMobile';
|
||||
@@ -188,7 +188,7 @@ const SectionTab = React.forwardRef(function SectionTab(
|
||||
{...rest}
|
||||
icon={icon ? <SectionIcon isActive={isActive} icon={icon} /> : null}
|
||||
label={title}
|
||||
trailing={isGroup ? <DropdownChevron /> : null}
|
||||
trailing={isGroup ? <ToggleChevron /> : null}
|
||||
active={isActive}
|
||||
className={tcls(
|
||||
'group/dropdown relative my-1.5 overflow-visible',
|
||||
|
||||
@@ -38,14 +38,8 @@ export function PageDocumentItem(props: { page: ClientTOCPageDocument }) {
|
||||
) : null
|
||||
}
|
||||
>
|
||||
{page.emoji || page.icon ? (
|
||||
<span className="flex items-center gap-3">
|
||||
<TOCPageIcon page={page} />
|
||||
{page.title}
|
||||
</span>
|
||||
) : (
|
||||
page.title
|
||||
)}
|
||||
<TOCPageIcon page={page} />
|
||||
{page.title}
|
||||
</ToggleableLinkItem>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -12,11 +12,13 @@ import { TOCPageIcon } from './TOCPageIcon';
|
||||
export function PageLinkItem(props: { page: ClientTOCPageLink }) {
|
||||
const { page } = props;
|
||||
|
||||
const isExternal = page.target.kind === 'url';
|
||||
|
||||
return (
|
||||
<li className={tcls('flex', 'flex-col')}>
|
||||
<Link
|
||||
href={page.href ?? '#'}
|
||||
classNames={['PageLinkItemStyles']}
|
||||
classNames={['ToggleableLinkItemStyles']}
|
||||
insights={{
|
||||
type: 'link_click',
|
||||
link: {
|
||||
@@ -27,21 +29,24 @@ export function PageLinkItem(props: { page: ClientTOCPageLink }) {
|
||||
>
|
||||
<TOCPageIcon page={page} />
|
||||
{page.title}
|
||||
<Icon
|
||||
icon="arrow-up-right-from-square"
|
||||
className={tcls(
|
||||
'size-3',
|
||||
'mr-1',
|
||||
'mt-1',
|
||||
'place-self-start',
|
||||
'shrink-0',
|
||||
'text-current',
|
||||
'transition-colors',
|
||||
'[&>path]:transition-opacity',
|
||||
'[&>path]:opacity-[0.4]',
|
||||
'group-hover:[&>path]:opacity-11'
|
||||
)}
|
||||
/>
|
||||
{isExternal ? (
|
||||
<Icon
|
||||
icon="arrow-up-right"
|
||||
className={tcls(
|
||||
'size-3',
|
||||
'ml-auto',
|
||||
'mr-1',
|
||||
'mt-1',
|
||||
'place-self-start',
|
||||
'shrink-0',
|
||||
'text-current',
|
||||
'transition-all',
|
||||
'opacity-6',
|
||||
'group-hover/toclink:opacity-11',
|
||||
'contrast-more:opacity-11'
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { useCurrentPagePath } from '../hooks';
|
||||
import { Link, type LinkInsightsProps, type LinkProps } from '../primitives';
|
||||
import { Button, Link, type LinkInsightsProps, type LinkProps, ToggleChevron } from '../primitives';
|
||||
import { useScrollToActiveTOCItem } from './TOCScroller';
|
||||
|
||||
/**
|
||||
@@ -138,42 +133,28 @@ function Toggler(props: {
|
||||
isOpen: boolean;
|
||||
onToggle: () => void;
|
||||
}) {
|
||||
const { isLinkActive, isOpen, onToggle } = props;
|
||||
const { isOpen, onToggle } = props;
|
||||
return (
|
||||
<span
|
||||
className={tcls(
|
||||
'group',
|
||||
'relative',
|
||||
'rounded-full',
|
||||
'straight-corners:rounded-xs',
|
||||
'w-5',
|
||||
'h-5',
|
||||
'after:grid-area-1-1',
|
||||
'after:absolute',
|
||||
'after:-top-1',
|
||||
'after:grid',
|
||||
'after:-left-1',
|
||||
'after:w-7',
|
||||
'after:h-7',
|
||||
'hover:bg-tint-active',
|
||||
'hover:text-current',
|
||||
isLinkActive && 'hover:bg-tint-hover'
|
||||
)}
|
||||
<Button
|
||||
icon={
|
||||
<ToggleChevron
|
||||
open={isOpen}
|
||||
orientation="right-to-down"
|
||||
className="m-0! size-3! opacity-6 group-hover:opacity-11"
|
||||
/>
|
||||
}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onToggle();
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
icon="chevron-right"
|
||||
className={tcls(
|
||||
'm-1 grid size-3 shrink-0 text-current opacity-6 transition',
|
||||
'group-hover:opacity-11 contrast-more:opacity-11',
|
||||
isOpen ? 'rotate-90' : 'rotate-0'
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
label={undefined}
|
||||
size="xsmall"
|
||||
iconOnly
|
||||
variant="blank"
|
||||
className="ml-auto text-current hover:bg-tint-base"
|
||||
tabIndex={-1} // Prevent focus on the button since it's already inside a clickable link that performs the same toggle action.
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,6 @@
|
||||
export const PageLinkItemStyles = [
|
||||
'flex',
|
||||
'justify-start',
|
||||
'items-center',
|
||||
'gap-3',
|
||||
'p-1.5',
|
||||
'pl-3',
|
||||
'text-sm',
|
||||
'transition-colors',
|
||||
'duration-100',
|
||||
'text-tint-strong/7',
|
||||
'rounded-md',
|
||||
'straight-corners:rounded-none',
|
||||
'circular-corners:rounded-xl',
|
||||
'before:content-none',
|
||||
'font-normal',
|
||||
'hover:bg-tint',
|
||||
'hover:text-tint-strong',
|
||||
];
|
||||
|
||||
export const ToggleableLinkItemStyles = [
|
||||
'group/toclink toclink relative transition-colors',
|
||||
'flex flex-row justify-between',
|
||||
'flex flex-row justify-start items-center gap-3',
|
||||
'circular-corners:rounded-2xl rounded-md straight-corners:rounded-none p-1.5 pl-3',
|
||||
'text-balance font-normal text-sm text-tint-strong/7 hover:bg-tint-hover hover:text-tint-strong contrast-more:text-tint-strong',
|
||||
'contrast-more:hover:text-tint-strong contrast-more:hover:ring-1 contrast-more:hover:ring-tint-12',
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as RadixDropdownMenu from '@radix-ui/react-dropdown-menu';
|
||||
|
||||
import { assert } from 'ts-essentials';
|
||||
import { Link, type LinkInsightsProps } from '.';
|
||||
import { ToggleChevron } from './ToggleChevron';
|
||||
|
||||
export type DropdownButtonProps<E extends HTMLElement = HTMLElement> = Omit<
|
||||
Partial<DetailedHTMLProps<HTMLAttributes<E>, E>>,
|
||||
@@ -99,26 +100,6 @@ export function DropdownMenu(props: {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animated chevron to display in the dropdown button.
|
||||
*/
|
||||
export function DropdownChevron() {
|
||||
return (
|
||||
<Icon
|
||||
icon="chevron-down"
|
||||
className={tcls(
|
||||
'shrink-0',
|
||||
'opacity-6',
|
||||
'size-3',
|
||||
'transition-all',
|
||||
'group-hover/dropdown:opacity-11',
|
||||
'group-data-[state=open]/dropdown:opacity-11',
|
||||
'group-data-[state=open]/dropdown:rotate-180'
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Button with a chevron for use in dropdowns.
|
||||
*/
|
||||
@@ -131,7 +112,7 @@ export function DropdownButton(props: {
|
||||
return (
|
||||
<div className={tcls('group/dropdown', 'flex', 'items-center', className)}>
|
||||
{children}
|
||||
<DropdownChevron />
|
||||
<ToggleChevron />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { ClassValue } from '@/lib/tailwind';
|
||||
|
||||
import { RecordCardStyles } from '../DocumentView/Table/styles';
|
||||
import {
|
||||
PageLinkItemStyles,
|
||||
ToggleableLinkItemActiveStyles,
|
||||
ToggleableLinkItemStyles,
|
||||
} from '../TableOfContents/styles';
|
||||
@@ -14,7 +13,6 @@ const styles = {
|
||||
CardStyles,
|
||||
ButtonStyles,
|
||||
RecordCardStyles,
|
||||
PageLinkItemStyles,
|
||||
ToggleableLinkItemStyles,
|
||||
ToggleableLinkItemActiveStyles,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
import { Icon, type IconName } from '@gitbook/icons';
|
||||
|
||||
/**
|
||||
* Animated chevron to display in dropdowns and other toggleable elements.
|
||||
* Uses the `data-[state=open]` attribute to animate the chevron, or you can pass it an `open` prop to control the state.
|
||||
*/
|
||||
export function ToggleChevron(props: {
|
||||
open?: boolean;
|
||||
orientation?: 'down-to-up' | 'right-to-down'; // The direction of the chevron when open.
|
||||
className?: ClassValue;
|
||||
}) {
|
||||
const {
|
||||
open,
|
||||
orientation = 'down-to-up',
|
||||
className = 'opacity-6 group-hover/dropdown:opacity-11',
|
||||
} = props;
|
||||
|
||||
const classes = {
|
||||
'down-to-up': {
|
||||
icon: 'chevron-down',
|
||||
animation: 'rotate-180',
|
||||
autoAnimation: 'group-data-[state=open]/dropdown:rotate-180 group-open:rotate-180',
|
||||
},
|
||||
'right-to-down': {
|
||||
icon: 'chevron-right',
|
||||
animation: 'rotate-90',
|
||||
autoAnimation: 'group-data-[state=open]/dropdown:rotate-90 group-open:rotate-90',
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Icon
|
||||
icon={classes[orientation].icon as IconName}
|
||||
className={tcls(
|
||||
'shrink-0',
|
||||
open ? classes[orientation].animation : classes[orientation].autoAnimation,
|
||||
'size-3',
|
||||
'transition-all',
|
||||
className
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -14,3 +14,4 @@ export * from './LoadingStateProvider';
|
||||
export * from './HoverCard';
|
||||
export * from './DropdownMenu';
|
||||
export * from './Input';
|
||||
export * from './ToggleChevron';
|
||||
|
||||
Reference in New Issue
Block a user