Style PR (#84)

* fixes for table values

* color tweaks rating

* inc legibility on aside active

* add tab separators

* fix hint icon

* fix header colors & remove custom balance

* Better mobile burger colors

* remove border from logofallback img

* style divider dark mode

* compact header + file + expandable hover + mt mobile nav

* testing file types
This commit is contained in:
Sebastian Graz
2024-01-04 18:43:37 +01:00
committed by GitHub
parent 87e67866a4
commit ccfcaa590b
20 changed files with 195 additions and 56 deletions
+1 -7
View File
@@ -19,7 +19,7 @@
@apply gutter-stable;
}
h1 {
@apply tracking-[-0.025em] text-dark dark:text-light textwrap-balance;
@apply tracking-[-0.025em] text-dark dark:text-light text-balance;
}
h2,
h3,
@@ -101,12 +101,6 @@
.gutter-stable {
scrollbar-gutter: stable;
}
.textwrap-balance {
text-wrap: balance;
}
.textwrap-pretty {
text-wrap: pretty;
}
.triangle {
position: relative;
+1 -1
View File
@@ -54,7 +54,7 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
'right-4',
'left-16',
'max-w-md',
'textwrap-balance',
'text-balance',
'sm:left-auto',
'dark:ring-light/2',
'dark:bg-dark',
+1 -1
View File
@@ -7,5 +7,5 @@ import { BlockProps } from './Block';
export function Divider(props: BlockProps<DocumentBlockDivider>) {
const { style } = props;
return <hr className={tcls(style)} />;
return <hr className={tcls(style, 'border-dark/2', 'dark:border-light/2')} />;
}
@@ -23,7 +23,7 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
<details
className={tcls(
style,
'group/expandable',
'shadow-dark/1',
'bg-gradient-to-t',
'from-light-1',
@@ -31,7 +31,6 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
'border',
'border-b-0',
'border-light-3/8',
'transition-color',
//all
'[&]:mt-[0px]',
//select first child
@@ -63,8 +62,10 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
'list-none',
'select-none',
'transition-colors',
'group-hover/expandable:text-dark-5/7',
'group-open:text-dark-5/7',
'dark:group-open:text-light-5',
'dark:group-hover/expandable:text-light-5',
'[&::-webkit-details-marker]:hidden',
)}
>
@@ -74,8 +75,9 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
'w-4',
'h-4',
'mr-2',
'mb-1',
'transition-transform',
'shrink-0',
'transition-all',
'group-open:rotate-90',
)}
/>
@@ -86,7 +88,7 @@ export function Expandable(props: BlockProps<DocumentBlockExpandable>) {
document={document}
ancestorBlocks={[...ancestorBlocks, block]}
context={context}
style={['px-10', 'pb-3', 'space-y-3']}
style={['px-10', 'pb-5', 'space-y-3']}
/>
</details>
);
+86 -7
View File
@@ -1,4 +1,7 @@
import IconDownload from '@geist-ui/icons/download';
import IconFileText from '@geist-ui/icons/fileText';
import IconImage from '@geist-ui/icons/image';
import IconPaperClip from '@geist-ui/icons/paperclip';
import { DocumentBlockFile } from '@gitbook/api';
import { getRevisionFile } from '@/lib/api';
@@ -16,31 +19,107 @@ export async function File(props: BlockProps<DocumentBlockFile>) {
return null;
}
const contentType = (() => {
switch (file.contentType) {
case 'application/pdf':
case 'application/x-pdf':
return 'pdf';
case 'image/png':
case 'image/jpeg':
case 'image/gif':
case 'image/webp':
case 'image/tiff':
case 'image/svg+xml':
return 'image';
case 'application/zip':
case 'application/x-7z-compressed':
case 'application/x-zip-compressed':
case 'application/x-tar':
case 'application/x-rar-compressed':
case 'application/vnd.rar':
return 'archive';
default:
return null;
}
})();
const icon = (() => {
switch (contentType) {
case 'pdf':
return <IconFileText />;
case 'image':
return <IconImage />;
case 'archive':
return <IconPaperClip />;
default:
return <IconDownload />;
}
})();
return (
<a
href={file.downloadURL}
download={file.name}
className={tcls(
'group/file',
'flex',
'flex-row',
'items-center',
'rounded',
'border',
'border-b-0',
'px-5',
'py-2',
'py-3',
'border-dark/3',
'hover:border-dark/5',
//all
'[&]:mt-[0px]',
//select first child
'[&:first-child]:mt-5',
'[&:first-child]:rounded-t-lg',
//select first in group
'[:not(&)_+&]:mt-5',
'[:not(&)_+&]:rounded-t-lg',
//select last in group
'[&:not(:has(+_&))]:mb-5',
'[&:not(:has(+_&))]:rounded-b-lg',
'[&:not(:has(+_&))]:border-b',
'hover:text-primary-600',
'dark:border-light/3',
'dark:hover:border-light/4',
'dark:hover:text-primary-300',
style,
)}
>
<div className={tcls('mr-5')}>
<IconDownload className={tcls('w-6', 'h-6')} />
<div
className={tcls(
'min-w-14',
'mr-5',
'pr-5',
'flex',
'flex-col',
'items-center',
'gap-1',
'border-r',
'border-dark/2',
'dark:border-light/2',
)}
>
<div className={tcls('*:w-5', '*:h-5', '*:stroke-primary')}>{icon}</div>
<div
className={tcls(
'text-xs',
'text-dark-5/8',
'group-hover/file:text-dark',
'dark:text-light-4/7',
'dark:group-hover/file:text-light',
)}
>
{getHumanFileSize(file.size)}
</div>
</div>
<div>
<div className={tcls('text-base')}>{file.name}</div>
<div className={tcls('text-xs')}>{getHumanFileSize(file.size)}</div>
<div className={tcls('text-sm', 'opacity-9', 'dark:opacity-8')}>{contentType}</div>
</div>
</a>
);
@@ -41,22 +41,40 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
);
case 'rating':
const rating = value as number;
const max = definition.max;
return (
<Tag className={tcls('text-primary')}>
<Tag className={tcls('inline-grid')}>
{value ? (
<span
role="meter"
aria-label={definition.title ?? ''}
aria-valuenow={rating}
aria-valuemin={1}
aria-valuemax={definition.max}
className={tcls('inline-flex', 'gap-1')}
>
{Array.from({ length: rating }).map((_, i) => (
<IconStar key={i} className={tcls('size-4')} />
))}
</span>
<>
<span className={tcls('inline-flex', 'grid-area-1-1', 'gap-0.5')}>
{Array.from({ length: max }).map((_, i) => (
<IconStar
key={i}
className={tcls(
'size-[15px]',
'stroke-primary-700/5',
'dark:stroke-primary-300/5',
)}
/>
))}
</span>
<span
role="meter"
aria-label={definition.title ?? ''}
aria-valuenow={rating}
aria-valuemin={1}
aria-valuemax={definition.max}
className={tcls('inline-flex', 'grid-area-1-1', 'gap-0.5')}
>
{Array.from({ length: rating }).map((_, i) => (
<IconStar
key={i}
className={tcls('size-[15px]', 'stroke-primary')}
/>
))}
</span>
</>
) : null}
</Tag>
);
@@ -106,7 +124,7 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
case 'content-ref': {
const resolved = value ? await context.resolveContentRef(value as ContentRef) : null;
return (
<Tag className={tcls('text-base')}>
<Tag className={tcls('text-base', 'text-balance')}>
{resolved ? <Link href={resolved.href}>{resolved.text}</Link> : null}
</Tag>
);
@@ -33,7 +33,7 @@ export async function RecordRow(
'dark:border-light/2',
)}
>
<div className={tcls('pr-4 ', 'textwrap-balance')}>
<div className={tcls('pr-4 ', 'text-balance')}>
<RecordColumnValue key={column} {...props} column={column} />
</div>
</td>
@@ -151,7 +151,7 @@ export function ViewGrid(props: TableViewProps<DocumentTableViewGrid>) {
className={tcls(
tableTH,
'align-baseline',
'textwrap-balance',
'text-balance',
'border-b',
'border-b-dark/4',
'text-left',
@@ -31,7 +31,17 @@ export function DynamicTabs(props: {
style,
)}
>
<div role="tablist" className={tcls('flex', 'flex-row', 'p-4', 'space-x-1.5')}>
<div
role="tablist"
className={tcls(
'group/tabs',
'inline-flex',
'flex-row',
'p-4',
'self-start',
'space-x-1.5',
)}
>
{tabs.map((tab) => (
<button
key={tab.id}
@@ -51,14 +61,33 @@ export function DynamicTabs(props: {
'transition-colors',
'font-semibold',
'text-dark-4',
'after:transition-colors',
'after:group-hover/tabs:border-transparent',
'after:border-r',
'after:border-dark/4',
'after:left-4',
'after:relative',
'last:after:border-transparent',
'hover:bg-light-2',
'dark:text-light-5',
'dark:hover:bg-dark-2',
'dark:hover:text-light-4',
'dark:after:border-light/2',
active === tab.id
? [
'active-tab',
'text-dark-4',
'bg-light-3',
'after:[&.active-tab]:border-transparent',
'after:[:has(+_&.active-tab)]:border-transparent',
'after:[:has(&_+)]:border-transparent',
'hover:bg-light-4',
'dark:bg-dark-4',
'dark:text-light',
+1
View File
@@ -23,6 +23,7 @@ export function CompactHeader(props: {
<div
className={tcls(
'hidden',
'pr-4',
'lg:flex',
'lg:flex-col',
'flex-wrap',
+11 -6
View File
@@ -93,16 +93,21 @@ export function Header(props: {
style={
!isCustomizationDefault && withTopHeader
? [
'bg-header-background-400/6',
'text-header-background-200',
'ring-light/2',
'[&>span]:text-header-background-200',
'[&_svg]:stroke-header-background-200',
'bg-header-background-400/8',
'shadow-sm',
'text-header-link/8',
'ring-header-background-200/5',
'[&>span]:text-header-link/7',
'[&_svg]:stroke-header-link',
'dark:bg-header-link-600/3',
'dark:ring-header-link-600/2',
'dark:text-header-link/7',
'dark:[&_svg]:stroke-header-link/7',
]
: null
}
>
<span>{t(getSpaceLanguage(customization), 'search')}</span>
<p>{t(getSpaceLanguage(customization), 'search')}</p>
</SearchButton>
</Suspense>
</div>
+12 -5
View File
@@ -1,4 +1,4 @@
import { Collection, CustomizationSettings, Space } from '@gitbook/api';
import { Collection, CustomizationHeaderPreset, CustomizationSettings, Space } from '@gitbook/api';
import Link from 'next/link';
import { HeaderMobileMenu } from '@/components/Header/HeaderMobileMenu';
@@ -17,12 +17,19 @@ interface HeaderLogoProps {
/**
* Render the logo for a space using the customization settings.
*/
export function HeaderLogo(props: HeaderLogoProps) {
const { customization } = props;
const isCustomizationDefault =
customization.header.preset === CustomizationHeaderPreset.Default;
return (
<div className={tcls('flex', 'flex-row', 'gap-3')}>
<HeaderMobileMenu className={tcls('lg:hidden')} />
<HeaderMobileMenu
className={tcls(
'lg:hidden',
isCustomizationDefault ? ['text-dark', 'dark:text-light'] : 'text-header-link',
)}
/>
<Link
href={absoluteHref('')}
className={tcls('group/headerlogo', 'flex', 'flex-row', 'items-center', 'shrink-0')}
@@ -104,12 +111,12 @@ function LogoFallback(props: HeaderLogoProps) {
}
sizes={[]}
fetchPriority="high"
style={['w-8', 'h-8', 'rounded', 'overflow-hidden', 'border', 'border-dark/2']}
style={['w-8', 'h-8']}
/>
<h1
className={tcls(
'textwrap-balance',
'text-balance',
'flex',
'leading-tight',
'tracking-tight',
+3 -2
View File
@@ -43,9 +43,10 @@ export function HeaderMobileMenu(props: Partial<React.ButtonHTMLAttributes<HTMLB
>
<IconMenu
className={tcls(
'w-8',
'h-8',
'w-7',
'h-7',
'rounded',
'text-inherit',
'hover:bg-dark/3',
'p-[0.25rem]',
'dark:hover:bg-light/2',
@@ -43,8 +43,7 @@ export function ScrollSectionsList(props: { sections: DocumentSection[] }) {
'py-1',
'ps-3',
'hover:text-primary',
'transition-colors',
'duration-200',
'transition-all',
'border-l',
'border-transparent',
section.depth > 1 ? ['ps-6', 'opacity-8'] : null,
@@ -54,6 +53,7 @@ export function ScrollSectionsList(props: { sections: DocumentSection[] }) {
'border-primary',
'dark:text-primary-400',
'dark:border-primary-400',
'opacity-[1]',
]
: '',
)}
+2
View File
@@ -52,8 +52,10 @@ export function SearchButton(props: { children?: React.ReactNode; style?: ClassV
'dark:bg-light/1',
'dark:ring-light/1',
'dark:text-light/7',
'[&>p]:hidden',
'[&>span]:hidden',
'md:justify-start',
'md:[&>p]:flex',
'md:[&>span]:flex',
'md:w-full',
'md:px-3.5',
@@ -68,7 +68,7 @@ export function TableOfContents(props: {
{header ? header : null}
<div
className={tcls(
withHeaderOffset ? 'pt-4' : null,
withHeaderOffset ? 'pt-4' : ['pt-4', 'lg:pt-0'],
'hidden',
'lg:flex',
'flex-grow',
@@ -101,7 +101,7 @@ export function ToggleableLinkItem(props: {
'text-sm',
'transition-colors',
'relative',
'textwrap-balance',
'text-balance',
'before:border-l',
'before:absolute',
'before:left-[-1px]',
+1
View File
@@ -12,6 +12,7 @@ export function Link(props: LinkProps & { children: React.ReactNode }) {
className={tcls(
'underline',
'underline-offset-2',
'decoration-primary/6',
'text-primary',
'hover:text-primary-700',
'transition-colors',
+1 -1
View File
@@ -62,7 +62,7 @@ export const LoadingPane = (props: {
'will-change-transform',
pulse
? 'animate-[pulse_6s_cubic-bezier(.44,.12,.29,.94)_infinite]'
? 'animate-[pulseAlt_6s_cubic-bezier(.44,.12,.29,.94)_infinite]'
: 'animate-[rotateLoop_2s_linear_infinite]',
pulse
? `[background-image:radial-gradient(circle_closest-side,_var(--tw-gradient-stops)_0,_var(--tw-gradient-stops)_33%,_var(--tw-gradient-stops)_66%)]`
+1 -1
View File
@@ -68,7 +68,7 @@ const config: Config = {
'header-link': generateShades('header-link'),
},
keyframes: {
pulse: {
pulseAlt: {
'0%': {
transform: 'scale(0.01)',
opacity: '0',