Skip to content

Implement a StylesProvider #3352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { tcls } from '@/lib/tailwind';
import { type CustomizationAnnouncement, SiteInsightsLinkPosition } from '@gitbook/api';
import { Icon, type IconName } from '@gitbook/icons';
import { CONTAINER_STYLE } from '../layout';
import { Link, linkStyles } from '../primitives';
import { Link } from '../primitives';
import { LinkStyles } from '../primitives/styles';
import { ANNOUNCEMENT_CSS_CLASS, ANNOUNCEMENT_STORAGE_KEY } from './constants';

/**
Expand Down Expand Up @@ -58,7 +59,7 @@ export function AnnouncementBanner(props: {
<div>
{announcement.message}
{hasLink ? (
<div className={tcls(linkStyles, style.link, 'ml-1 inline')}>
<div className={tcls(LinkStyles, style.link, 'ml-1 inline')}>
{contentRef?.icon ? (
<span className="mr-1 ml-2 *:inline">
{contentRef?.icon}
Expand Down
30 changes: 4 additions & 26 deletions packages/gitbook/src/components/DocumentView/Table/RecordCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
import { LinkBox, LinkOverlay } from '@/components/primitives';
import { Image } from '@/components/utils';
import { resolveContentRef } from '@/lib/references';
import { type ClassValue, tcls } from '@/lib/tailwind';
import { tcls } from '@/lib/tailwind';

import { RecordColumnValue } from './RecordColumnValue';
import type { TableRecordKV, TableViewProps } from './Table';
import { RecordCardStyles } from './styles';
import { getRecordValue } from './utils';

export async function RecordCard(
Expand Down Expand Up @@ -143,35 +144,12 @@ export async function RecordCard(
</div>
);

const style = [
'group',
'grid',
'shadow-1xs',
'shadow-tint-9/1',
'depth-flat:shadow-none',
'rounded',
'straight-corners:rounded-none',
'circular-corners:rounded-xl',
'dark:shadow-transparent',

'before:pointer-events-none',
'before:grid-area-1-1',
'before:transition-shadow',
'before:w-full',
'before:h-full',
'before:rounded-[inherit]',
'before:ring-1',
'before:ring-tint-12/2',
'before:z-10',
'before:relative',
] as ClassValue;

if (target && targetRef) {
return (
// We don't use `Link` directly here because we could end up in a situation where
// a link is rendered inside a link, which is not allowed in HTML.
// It causes an hydration error in React.
<LinkBox href={target.href} className={tcls(style, 'hover:before:ring-tint-12/5')}>
<LinkBox href={target.href} classNames={['RecordCardStyles']}>
<LinkOverlay
href={target.href}
insights={{
Expand All @@ -187,5 +165,5 @@ export async function RecordCard(
);
}

return <div className={tcls(style)}>{body}</div>;
return <div className={tcls(RecordCardStyles)}>{body}</div>;
}
26 changes: 26 additions & 0 deletions packages/gitbook/src/components/DocumentView/Table/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { ClassValue } from '@/lib/tailwind';

export const RecordCardStyles = [
'group',
'grid',
'shadow-1xs',
'shadow-tint-9/1',
'depth-flat:shadow-none',
'rounded',
'straight-corners:rounded-none',
'circular-corners:rounded-xl',
'dark:shadow-transparent',

'before:pointer-events-none',
'before:grid-area-1-1',
'before:transition-shadow',
'before:w-full',
'before:h-full',
'before:rounded-[inherit]',
'before:ring-1',
'before:ring-tint-12/2',
'before:z-10',
'before:relative',

'hover:before:ring-tint-12/5',
] as ClassValue;
20 changes: 1 addition & 19 deletions packages/gitbook/src/components/TableOfContents/PageLinkItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,7 @@ export async function PageLinkItem(props: { page: RevisionPageLink; context: Git
<li className={tcls('flex', 'flex-col')}>
<Link
href={resolved?.href ?? '#'}
className={tcls(
'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'
)}
classNames={['PageLinkItemStyles']}
insights={{
type: 'link_click',
link: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,42 +66,10 @@ function LinkItem(
href={href}
insights={insights}
aria-current={isActive ? 'page' : undefined}
className={tcls(
'group/toclink toclink relative transition-colors',
'flex flex-row justify-between',
'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',
'hover:contrast-more:text-tint-strong hover:contrast-more:ring-1 hover:contrast-more:ring-tint-12',
'before:contents[] before:-left-px before:absolute before:inset-y-0',
'sidebar-list-line:rounded-l-none sidebar-list-line:before:w-px sidebar-list-default:[&+div_a]:rounded-l-none [&+div_a]:pl-5 sidebar-list-default:[&+div_a]:before:w-px',

isActive && [
'font-semibold',
'sidebar-list-line:before:w-0.5',

'before:bg-primary-solid',
'text-primary-subtle',
'contrast-more:text-primary',

'sidebar-list-pill:bg-primary',
'[html.sidebar-list-pill.theme-muted_&]:bg-primary-hover',
'[html.sidebar-list-pill.theme-bold.tint_&]:bg-primary-hover',
'[html.sidebar-filled.sidebar-list-pill.theme-muted_&]:bg-primary',
'[html.sidebar-filled.sidebar-list-pill.theme-bold.tint_&]:bg-primary',

'hover:bg-primary-hover',
'hover:text-primary',
'hover:before:bg-primary-solid-hover',
'sidebar-list-pill:hover:bg-primary-hover',

'contrast-more:text-primary',
'contrast-more:hover:text-primary-strong',
'contrast-more:bg-primary',
'contrast-more:ring-1',
'contrast-more:ring-primary',
'contrast-more:hover:ring-primary-hover',
]
)}
classNames={[
'ToggleableLinkItemStyles',
...(isActive ? ['ToggleableLinkItemActiveStyles' as const] : []),
]}
>
{children}
</Link>
Expand Down
56 changes: 56 additions & 0 deletions packages/gitbook/src/components/TableOfContents/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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',
'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',
'hover:contrast-more:text-tint-strong hover:contrast-more:ring-1 hover:contrast-more:ring-tint-12',
'before:contents[] before:-left-px before:absolute before:inset-y-0',
'sidebar-list-line:rounded-l-none sidebar-list-line:before:w-px sidebar-list-default:[&+div_a]:rounded-l-none [&+div_a]:pl-5 sidebar-list-default:[&+div_a]:before:w-px',
];

export const ToggleableLinkItemActiveStyles = [
'font-semibold',
'sidebar-list-line:before:w-0.5',

'before:bg-primary-solid',
'text-primary-subtle',
'contrast-more:text-primary',

'sidebar-list-pill:bg-primary',
'[html.sidebar-list-pill.theme-muted_&]:bg-primary-hover',
'[html.sidebar-list-pill.theme-bold.tint_&]:bg-primary-hover',
'[html.sidebar-filled.sidebar-list-pill.theme-muted_&]:bg-primary',
'[html.sidebar-filled.sidebar-list-pill.theme-bold.tint_&]:bg-primary',

'hover:bg-primary-hover',
'hover:text-primary',
'hover:before:bg-primary-solid-hover',
'sidebar-list-pill:hover:bg-primary-hover',

'contrast-more:text-primary',
'contrast-more:hover:text-primary-strong',
'contrast-more:bg-primary',
'contrast-more:ring-1',
'contrast-more:ring-primary',
'contrast-more:hover:ring-primary-hover',
];
50 changes: 11 additions & 39 deletions packages/gitbook/src/components/primitives/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { type ClassValue, tcls } from '@/lib/tailwind';

import { Icon, type IconName } from '@gitbook/icons';
import { Link, type LinkInsightsProps } from './Link';
import { useClassnames } from './StyleProvider';

type ButtonProps = {
href?: string;
Expand All @@ -18,7 +19,7 @@ type ButtonProps = {
} & LinkInsightsProps &
HTMLAttributes<HTMLElement>;

const variantClasses = {
export const variantClasses = {
primary: [
'bg-primary-solid',
'text-contrast-primary-solid',
Expand Down Expand Up @@ -69,49 +70,15 @@ export function Button({

const sizeClasses = sizes[size] || sizes.default;

const domClassName = tcls(
'button',
'inline-flex',
'items-center',
'gap-2',
'rounded-md',
'straight-corners:rounded-none',
'circular-corners:rounded-full',
// 'place-self-start',

'ring-1',
'ring-tint',
'hover:ring-tint-hover',

'shadow-sm',
'shadow-tint',
'dark:shadow-tint-1',
'hover:shadow-md',
'active:shadow-none',
'depth-flat:shadow-none',

'contrast-more:ring-tint-12',
'contrast-more:hover:ring-2',
'contrast-more:hover:ring-tint-12',

'hover:scale-104',
'depth-flat:hover:scale-100',
'active:scale-100',
'transition-all',

'grow-0',
'shrink-0',
'truncate',
variantClasses[variant],
sizeClasses,
className
);
const domClassName = tcls(variantClasses[variant], sizeClasses, className);
const buttonOnlyClassNames = useClassnames(['ButtonStyles']);

if (href) {
return (
<Link
href={href}
className={domClassName}
classNames={['ButtonStyles']}
insights={insights}
aria-label={label}
target={target}
Expand All @@ -124,7 +91,12 @@ export function Button({
}

return (
<button type="button" className={domClassName} aria-label={label} {...rest}>
<button
type="button"
className={tcls(domClassName, buttonOnlyClassNames)}
aria-label={label}
{...rest}
>
{icon ? <Icon icon={icon} className={tcls('size-[1em]')} /> : null}
{iconOnly ? null : label}
</button>
Expand Down
23 changes: 1 addition & 22 deletions packages/gitbook/src/components/primitives/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,7 @@ export async function Card(
const { title, leadingIcon, href, preTitle, postTitle, style, insights } = props;

return (
<Link
href={href}
className={tcls(
'group',
'flex',
'flex-row',
'justify-between',
'items-center',
'gap-4',
'ring-1',
'ring-tint-subtle',
'rounded',
'straight-corners:rounded-none',
'circular-corners:rounded-2xl',
'px-5',
'py-3',
'transition-shadow',
'hover:ring-primary-hover',
style
)}
insights={insights}
>
<Link href={href} className={tcls(style)} classNames={['CardStyles']} insights={insights}>
{leadingIcon}
<span className={tcls('flex', 'flex-col', 'flex-1')}>
{preTitle ? (
Expand Down
Loading