From aab7d0bd7ae127be6fcb9ef42e62aedcfdcf4516 Mon Sep 17 00:00:00 2001 From: Sebastian Graz Date: Tue, 21 Nov 2023 18:29:36 +0100 Subject: [PATCH] Design pass (#8) * first stab at bullet points * setup theming, custom opacities, use of brand UI colors * color key change * delete brand * setup initial defaults * Add opacity parameter to primary color * style TOC * styling pass header, footer, hints, toc, trademark * table pass * style pass, typo, quote, tabs, search, theme, toc --- .env.example | 4 +-- src/app/[spaceId]/[[...pathname]]/layout.tsx | 21 ++++++----- src/app/[spaceId]/globals.css | 36 ++++++++++++++++++- .../DocumentView/BlockContentRef.tsx | 10 +++--- src/components/DocumentView/Blocks.tsx | 24 ++----------- src/components/DocumentView/Heading.tsx | 27 +++++++------- src/components/DocumentView/Hint.tsx | 22 ++++++------ src/components/DocumentView/Images.tsx | 1 + src/components/DocumentView/Link.tsx | 5 +-- src/components/DocumentView/ListItem.tsx | 7 ++-- src/components/DocumentView/ListOrdered.tsx | 2 +- src/components/DocumentView/ListTasks.tsx | 2 +- src/components/DocumentView/ListUnordered.tsx | 2 +- src/components/DocumentView/Paragraph.tsx | 2 +- .../DocumentView/Table/RecordRow.tsx | 11 +++++- .../DocumentView/Table/ViewGrid.tsx | 11 +++--- .../DocumentView/Tabs/DynamicTabs.tsx | 29 +++++++++++---- src/components/Footer/Footer.tsx | 8 ++--- .../Header/CollectionSpacesDropdown.tsx | 1 - src/components/Header/Header.tsx | 10 +++--- src/components/PageAside/PageAside.tsx | 2 +- .../PageAside/ScrollSectionsList.tsx | 6 ++-- src/components/PageBody/PageBody.tsx | 2 +- .../PageBody/PageFooterNavigation.tsx | 19 ++++++---- src/components/Search/HighlightQuery.tsx | 2 +- src/components/Search/SearchButton.tsx | 11 +++--- src/components/Search/SearchModal.tsx | 21 +++++++---- .../Search/SearchPageResultItem.tsx | 11 +++--- src/components/Search/SearchResults.tsx | 4 +-- .../Search/SearchSectionResultItem.tsx | 35 ++++++++++-------- .../TableOfContents/PageDocumentItem.tsx | 32 +++++++++++++---- .../TableOfContents/PageGroupItem.tsx | 4 +-- .../TableOfContents/TableOfContents.tsx | 2 -- ...bleLinkItem.tsx => ToggleableLinkItem.tsx} | 15 +++++--- src/components/TableOfContents/Trademark.tsx | 11 +++--- src/components/ThemeToggler/ThemeToggler.tsx | 23 +++++++----- src/components/utils/HexToRgb.tsx | 21 +++++++++++ tailwind.config.ts | 24 +++++++++++-- types/tailwind-shades.d.ts | 15 ++------ 39 files changed, 314 insertions(+), 181 deletions(-) rename src/components/TableOfContents/{ToggeableLinkItem.tsx => ToggleableLinkItem.tsx} (69%) create mode 100644 src/components/utils/HexToRgb.tsx diff --git a/.env.example b/.env.example index 7e5e978b8..7fc6b0862 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # Mode to serve only a single space # Ex: http://localhost:4000 -GITBOOK_MODE=single +# GITBOOK_MODE=single GITBOOK_SPACE_ID=your_space_id GITBOOK_TOKEN=your_token_here @@ -10,7 +10,7 @@ GITBOOK_MODE=multi # Mode to serve multiple spaces with the space url passed as a path # Ex: http://localhost:4000/docs.mycompany.com/page1 -GITBOOK_MODE=multi-path +# GITBOOK_MODE=multi-path # Other options: diff --git a/src/app/[spaceId]/[[...pathname]]/layout.tsx b/src/app/[spaceId]/[[...pathname]]/layout.tsx index dc2714463..f1809487e 100644 --- a/src/app/[spaceId]/[[...pathname]]/layout.tsx +++ b/src/app/[spaceId]/[[...pathname]]/layout.tsx @@ -4,6 +4,7 @@ import { Inter } from 'next/font/google'; import shadesOf from 'tailwind-shades'; import colors from 'tailwindcss/colors'; +import { hexToRgb } from '@/components/utils/HexToRgb'; import { tcls } from '@/lib/tailwind'; import { ClientLayout } from './ClientLayout'; @@ -24,30 +25,30 @@ export default async function SpaceRootLayout(props: { - + {children} @@ -55,12 +56,14 @@ export default async function SpaceRootLayout(props: { } type ColorInput = string | Record; -function generateCSSVariable(name: string, color: ColorInput) { +function generateColorVariable(name: string, color: ColorInput) { const shades: Record = typeof color === 'string' ? shadesOf(color) : color; return Object.entries(shades) .map(([key, value]) => { - return `--${name}-${key}: ${value};`; + // Check the original hex value + const rgbValue = hexToRgb(value); + return `--${name}-${key}: ${rgbValue};`; }) .join('\n'); } diff --git a/src/app/[spaceId]/globals.css b/src/app/[spaceId]/globals.css index 68cb03319..fefb83f39 100644 --- a/src/app/[spaceId]/globals.css +++ b/src/app/[spaceId]/globals.css @@ -2,5 +2,39 @@ @tailwind components; @tailwind utilities; -body { +@layer base { + :root { + --dark: 24 28 31; + --vanta: 2 12 13; + --light: 242 247 247; + --metal: 222 229 229; + --yellow: 244 226 141; + --teal: 63 137 161; + --pomegranate: 242 91 58; + --periwinkle: 172 198 238; + } + h1 { + @apply tracking-tighter; + @apply text-dark dark:text-light; + } + h2, + h3, + h4, + h5, + h6 { + @apply tracking-tight; + @apply text-dark dark:text-light; + } + body { + @apply text-dark/9 dark:text-light/9; + } + p { + @apply text-dark/9 dark:text-light/8; + } +} + +@layer utilities { + .linear-mask-gradient { + mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 96px, rgba(0, 0, 0, 0)); + } } diff --git a/src/components/DocumentView/BlockContentRef.tsx b/src/components/DocumentView/BlockContentRef.tsx index adddb7ba0..e8c73072d 100644 --- a/src/components/DocumentView/BlockContentRef.tsx +++ b/src/components/DocumentView/BlockContentRef.tsx @@ -23,12 +23,14 @@ export async function BlockContentRef(props: BlockProps 'items-center', 'rounded', 'border', - 'border-slate-200', - 'hover:border-slate-300', + 'border-dark/2', + 'hover:border-dark/4', 'px-5', 'py-2', - 'text-slate-500', - 'hover:text-slate-700', + 'hover:text-dark', + 'dark:border-light/2', + 'dark:hover:text-light', + 'dark:hover:border-light/4', style, )} > diff --git a/src/components/DocumentView/Blocks.tsx b/src/components/DocumentView/Blocks.tsx index 552184f7b..42f58e995 100644 --- a/src/components/DocumentView/Blocks.tsx +++ b/src/components/DocumentView/Blocks.tsx @@ -21,23 +21,9 @@ export function Blocks @@ -45,13 +31,7 @@ export function Blocks ))} diff --git a/src/components/DocumentView/Heading.tsx b/src/components/DocumentView/Heading.tsx index 5128e254b..4d48066b2 100644 --- a/src/components/DocumentView/Heading.tsx +++ b/src/components/DocumentView/Heading.tsx @@ -21,7 +21,9 @@ export function Heading(props: BlockProps) {
) { 'w-6', 'items-center', 'justify-center', - 'rounded-md', - 'text-slate-400', - 'shadow-sm', - 'ring-1', - 'ring-slate-900/5', - 'hover:text-slate-700', - 'hover:shadow', - 'hover:ring-slate-900/10', - 'dark:bg-slate-700', - 'dark:text-slate-300', + 'transition-colors', + 'dark:text-light/3', 'dark:shadow-none', 'dark:ring-0', )} > - +
diff --git a/src/components/DocumentView/Hint.tsx b/src/components/DocumentView/Hint.tsx index 618e1951d..79289f213 100644 --- a/src/components/DocumentView/Hint.tsx +++ b/src/components/DocumentView/Hint.tsx @@ -22,8 +22,7 @@ export function Hint(props: BlockProps) { 'flex-row', 'px-4', 'py-4', - 'bg-slate-50', - 'dark:bg-slate-900', + 'transition-colors', 'rounded', 'border-l-4', hintStyle.style, @@ -36,6 +35,7 @@ export function Hint(props: BlockProps) { 'items-center', 'justify-center', 'pr-3', + firstLine.lineHeight, hintStyle.iconStyle, )} @@ -46,7 +46,7 @@ export function Hint(props: BlockProps) { {...contextProps} ancestorBlocks={[...ancestorBlocks, block]} nodes={block.nodes} - style={['flex-1']} + style={['flex-1', 'space-y-8']} /> ); @@ -61,22 +61,22 @@ const HINT_STYLES: { } = { info: { icon: IconInfo, - iconStyle: ['text-blue-500'], - style: ['border-blue-500'], + iconStyle: ['text-current'], + style: ['border-dark/2', 'bg-dark/2', 'dark:bg-light/1', 'dark:border-light/3'], }, warning: { icon: IconAlertCircle, - iconStyle: ['text-orange-500'], - style: ['border-orange-500'], + iconStyle: ['text-yellow, dark:text-yellow/1, dark:text-yellow/8'], + style: ['border-yellow/4', 'bg-yellow', 'dark:bg-yellow/1'], }, danger: { icon: IconAlertTriangle, - iconStyle: ['text-red-500'], - style: ['border-red-500'], + iconStyle: ['text-pomegranate'], + style: ['border-pomegranate/4', 'bg-pomegranate/2', 'dark:bg-pomegranate/1'], }, success: { icon: IconCheckInCircle, - iconStyle: ['text-green-500'], - style: ['border-green-500'], + iconStyle: ['text-teal'], + style: ['border-teal/4', 'bg-teal/2', 'dark:bg-teal/2'], }, }; diff --git a/src/components/DocumentView/Images.tsx b/src/components/DocumentView/Images.tsx index 988d5298a..8535887d5 100644 --- a/src/components/DocumentView/Images.tsx +++ b/src/components/DocumentView/Images.tsx @@ -22,6 +22,7 @@ export function Images(props: BlockProps) { block.data.align === 'left' && 'justify-start', style, block.data.fullWidth ? 'max-w-full' : null, + 'justify-center', )} > {block.nodes.map((node: any, i: number) => ( diff --git a/src/components/DocumentView/Link.tsx b/src/components/DocumentView/Link.tsx index 8e2ff340e..4dd795b0f 100644 --- a/src/components/DocumentView/Link.tsx +++ b/src/components/DocumentView/Link.tsx @@ -20,10 +20,7 @@ export async function Link(props: InlineProps) { } return ( - + ); diff --git a/src/components/DocumentView/ListItem.tsx b/src/components/DocumentView/ListItem.tsx index c3b1acb45..b68557287 100644 --- a/src/components/DocumentView/ListItem.tsx +++ b/src/components/DocumentView/ListItem.tsx @@ -13,13 +13,14 @@ export function ListItem(props: BlockProps) { return (
  • {isTaskList ? ( -
    +
    ) : ( @@ -27,7 +28,7 @@ export function ListItem(props: BlockProps) { {...contextProps} nodes={block.nodes} ancestorBlocks={[...ancestorBlocks, block]} - blockStyle={tcls('mt-6', 'first:mt-0', 'last:mt-0')} + style={tcls('space-y-2')} /> )}
  • diff --git a/src/components/DocumentView/ListOrdered.tsx b/src/components/DocumentView/ListOrdered.tsx index 490f03daa..6ba9092b2 100644 --- a/src/components/DocumentView/ListOrdered.tsx +++ b/src/components/DocumentView/ListOrdered.tsx @@ -12,7 +12,7 @@ export function ListOrdered(props: BlockProps) { tag="ol" nodes={block.nodes} ancestorBlocks={[...ancestorBlocks, block]} - style={['list-decimal', 'ps-8', style]} + style={['list-decimal', 'ps-8', 'space-y-2', style]} /> ); } diff --git a/src/components/DocumentView/ListTasks.tsx b/src/components/DocumentView/ListTasks.tsx index 2eeadcc5f..cf370284c 100644 --- a/src/components/DocumentView/ListTasks.tsx +++ b/src/components/DocumentView/ListTasks.tsx @@ -12,7 +12,7 @@ export function ListTasks(props: BlockProps) { tag="ul" nodes={block.nodes} ancestorBlocks={[...ancestorBlocks, block]} - style={['list-disc', 'ps-8', style]} + style={['list-none', 'ps-4', 'space-y-2', style]} /> ); } diff --git a/src/components/DocumentView/ListUnordered.tsx b/src/components/DocumentView/ListUnordered.tsx index a9b94e238..26a1cd40c 100644 --- a/src/components/DocumentView/ListUnordered.tsx +++ b/src/components/DocumentView/ListUnordered.tsx @@ -12,7 +12,7 @@ export function ListUnordered(props: BlockProps) { tag="ul" nodes={block.nodes} ancestorBlocks={[...ancestorBlocks, block]} - style={['list-disc', 'ps-8', style]} + style={['list-disc', 'ps-8', 'space-y-2', style]} /> ); } diff --git a/src/components/DocumentView/Paragraph.tsx b/src/components/DocumentView/Paragraph.tsx index a46b62990..df0deeb54 100644 --- a/src/components/DocumentView/Paragraph.tsx +++ b/src/components/DocumentView/Paragraph.tsx @@ -9,7 +9,7 @@ export function Paragraph(props: BlockProps) { const { block, style, ...contextProps } = props; return ( -

    +

    ); diff --git a/src/components/DocumentView/Table/RecordRow.tsx b/src/components/DocumentView/Table/RecordRow.tsx index a5e4dc4ce..2603b71c8 100644 --- a/src/components/DocumentView/Table/RecordRow.tsx +++ b/src/components/DocumentView/Table/RecordRow.tsx @@ -16,7 +16,16 @@ export async function RecordRow( {view.columns.map((column) => { return ( - + ); diff --git a/src/components/DocumentView/Table/ViewGrid.tsx b/src/components/DocumentView/Table/ViewGrid.tsx index 2b1789aa0..76bf6971a 100644 --- a/src/components/DocumentView/Table/ViewGrid.tsx +++ b/src/components/DocumentView/Table/ViewGrid.tsx @@ -14,9 +14,6 @@ export function ViewGrid(props: TableViewProps) { style, 'table-auto', 'w-full', - 'border-collapse', - 'border', - 'border-slate-500', block.data.fullWidth ? ['max-w-full'] : null, )} > @@ -27,7 +24,13 @@ export function ViewGrid(props: TableViewProps) { return ( {block.data.definition[column].title} diff --git a/src/components/DocumentView/Tabs/DynamicTabs.tsx b/src/components/DocumentView/Tabs/DynamicTabs.tsx index 496286b63..eaa35c14f 100644 --- a/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -20,8 +20,18 @@ export function DynamicTabs(props: { const [active, setActive] = React.useState(null); return ( -
    -
    +
    +
    {tabs.map((tab) => ( ); } diff --git a/src/components/utils/HexToRgb.tsx b/src/components/utils/HexToRgb.tsx new file mode 100644 index 000000000..f0640ae5c --- /dev/null +++ b/src/components/utils/HexToRgb.tsx @@ -0,0 +1,21 @@ +export function hexToRgb(hex: string): string { + // Remove the hash at the beginning of the hex string if it exists + let sanitizedHex = hex.replace('#', ''); + + // If the hex is shorthand (3 characters), expand it to 6 characters + if (sanitizedHex.length === 3) { + sanitizedHex = sanitizedHex + .split('') + .map((char) => char + char) + .join(''); + } + + // Convert the hex to an integer and extract the RGB components + const intVal = parseInt(sanitizedHex, 16); + const r = (intVal >> 16) & 255; + const g = (intVal >> 8) & 255; + const b = intVal & 255; + + // Return the RGB values separated by spaces + return `${r} ${g} ${b}`; +} diff --git a/tailwind.config.ts b/tailwind.config.ts index 077a72258..41350895d 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,11 +1,22 @@ import type { Config } from 'tailwindcss'; -const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; +export const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; +export const opacities = [4, 8, 12, 16, 24, 40, 64, 72, 88, 96]; function generateShades(varName: string) { return shades.reduce( (acc, shade) => { - acc[shade] = `var(--${varName}-${shade})`; + acc[shade] = `rgb(var(--${varName}-${shade}) / )`; + return acc; + }, + { DEFAULT: `rgb(var(--${varName}-500) / )` } as Record, + ); +} + +function opacity() { + return opacities.reduce( + (acc, opacity, index) => { + acc[index + 1] = `${opacity / 100}`; return acc; }, {} as Record, @@ -24,10 +35,19 @@ const config: Config = { colors: { // Dynamic colors matching the customization settings primary: generateShades('primary-color'), + dark: 'rgb(var(--dark) / )', + light: 'rgb(var(--light) / )', + vanta: 'rgb(var(--vanta) / )', + metal: 'rgb(var(--metal) / )', + yellow: 'rgb(var(--yellow) / )', + periwinkle: 'rgb(var(--periwinkle) / )', + pomegranate: 'rgb(var(--pomegranate) / )', + teal: 'rgb(var(--teal) / )', 'header-background': generateShades('header-background'), 'header-link': generateShades('header-link'), }, }, + opacity: opacity(), }, plugins: [], }; diff --git a/types/tailwind-shades.d.ts b/types/tailwind-shades.d.ts index 8a5bb70a2..7e6a9b8c0 100644 --- a/types/tailwind-shades.d.ts +++ b/types/tailwind-shades.d.ts @@ -1,16 +1,7 @@ declare module 'tailwind-shades' { - export type Shade = { - 50: string; - 100: string; - 200: string; - 300: string; - 400: string; - 500: string; - 600: string; - 700: string; - 800: string; - 900: string; - }; + import { shades } from '../tailwind.config'; + + export type Shade = Record<(typeof shades)[number], string>; function shadesOf(color: string): Shade;