Skip to content

Commit

Permalink
chore: style the toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Apr 20, 2023
1 parent 45b79c1 commit adcdf97
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 83 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"@radix-ui/react-select": "^1.2.1",
"@radix-ui/react-toolbar": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.5",
"classnames": "^2.3.2",
"js-yaml": "4.1.0",
"mdast-util-directive": "2.2.4",
"mdast-util-from-markdown": "^1.3.0",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions src/import/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ import {
$createAdmonitionNode,
$createFrontmatterNode,
$createImageNode,
$createJsxNode,
$createSandpackNode,
$isAdmonitionNode,
AdmonitionKind,
AdmonitionNode,
FrontmatterNode,
ImageNode,
JsxNode,
SandpackNode,
} from '../nodes'
import { $createJsxNode, JsxNode } from '../nodes/Jsx'

type MdastNode = Mdast.Content

Expand Down
3 changes: 2 additions & 1 deletion src/nodes/Jsx/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
} from 'lexical'
import { MdxJsxAttribute } from 'mdast-util-mdx-jsx'
import React from 'react'
import { contentTheme, useEmitterValues } from '../../'
import { theme as contentTheme } from '../../content/theme'
import { useEmitterValues } from '../../system'
import { JsxEditorProps, JsxKind } from '../../types/NodeDecoratorsProps'

type updateFn = (node: LexicalNode) => void
Expand Down
1 change: 0 additions & 1 deletion src/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
28 changes: 18 additions & 10 deletions src/ui/ToolbarPlugin/BlockTypeSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ReactComponent as SelectedIcon } from '../icons/check_small.svg'
import { ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons'
import { AdmonitionKind } from '../../../nodes'
import { useEmitterValues, usePublisher } from '../../../system'
import classnames from 'classnames'

export type HeadingType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
export type BlockType = 'paragraph' | 'code' | 'quote' | HeadingType
Expand All @@ -18,14 +19,17 @@ export const BlockTypeSelect = () => {
const applyBlockType = usePublisher('applyBlockType')
return (
<Select.Root value={currentBlockType || ('' as const)} onValueChange={applyBlockType as (value: string) => void}>
<Select.Trigger aria-label="Block type" className="">
<Select.Trigger
aria-label="Block type"
className="group flex w-36 flex-row items-center rounded-md border-0 bg-transparent p-0 pl-4 pr-2 font-sans text-base hover:bg-primary-100 data-[state=open]:rounded-b-none data-[state=open]:bg-primary-100"
>
<Select.Value placeholder="Block type" />
<Select.Icon className="">
<Select.Icon className="ml-auto group-data-[state=open]:text-primary-900 [&_svg]:block">
<DropDownIcon />
</Select.Icon>
</Select.Trigger>
<Select.Portal className="">
<Select.Content className="" onCloseAutoFocus={(e) => e.preventDefault()}>
<Select.Portal className="font-sans">
<Select.Content className="w-36 rounded-b-md bg-primary-100" onCloseAutoFocus={(e) => e.preventDefault()} position="popper">
<Select.ScrollUpButton className="">
<ChevronUpIcon />
</Select.ScrollUpButton>
Expand All @@ -52,14 +56,18 @@ export const BlockTypeSelect = () => {
)
}

const SelectItem = React.forwardRef<HTMLDivElement | null, { children: React.ReactNode; value: string }>(
({ children, ...props }, forwardedRef) => {
const SelectItem = React.forwardRef<HTMLDivElement | null, { className?: string; children: React.ReactNode; value: string }>(
({ children, className, ...props }, forwardedRef) => {
return (
<Select.Item {...props} ref={forwardedRef} className="">
<Select.Item
{...props}
ref={forwardedRef}
className={classnames(
className,
`cursor-default px-4 py-2 data-[highlighted]:bg-primary-200 data-[state=checked]:bg-primary-300 data-[highlighted]:outline-0 flex`
)}
>
<Select.ItemText>{children}</Select.ItemText>
<Select.ItemIndicator className="">
<SelectedIcon />
</Select.ItemIndicator>
</Select.Item>
)
}
Expand Down
165 changes: 98 additions & 67 deletions src/ui/ToolbarPlugin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import { ReactComponent as MarkdownIcon } from './icons/markdown.svg'
import { ViewMode } from '../'
import { IS_BOLD, IS_CODE, IS_ITALIC, IS_UNDERLINE } from '../../FormatConstants'
import { useEmitterValues, usePublisher } from '../../system'
import classnames from 'classnames'
import { buttonClasses, childSvgClasses, toggleItemClasses } from '../commonCssClasses'

export const ToolbarPlugin = () => {
const [format, currentListType, viewMode, activeSandpackNode] = useEmitterValues(
const [currentFormat, currentListType, viewMode, activeSandpackNode] = useEmitterValues(
'currentFormat',
'currentListType',
'viewMode',
Expand Down Expand Up @@ -57,64 +59,66 @@ export const ToolbarPlugin = () => {
}

return (
<RadixToolbar.Root className="bg-slate-100" aria-label="Formatting options">
<RadixToolbar.ToggleGroup
type="single"
aria-label="Text formatting"
value={format & IS_BOLD ? 'on' : 'off'}
onValueChange={applyFormat.bind(null, 'bold')}
>
<ToolbarToggleItem value="on" aria-label="Bold">
<RadixToolbar.Root
className="mb-6 flex flex-row gap-2 rounded-md border-2 border-solid border-surface-50 p-2"
aria-label="Formatting options"
>
<GroupGroup>
<ToggleSingleGroupWithItem
className="[&_button]:rounded-l-md"
aria-label="Bold"
on={(currentFormat & IS_BOLD) !== 0}
onValueChange={applyFormat.bind(null, 'bold')}
>
<BoldIcon />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
<RadixToolbar.ToggleGroup
type="single"
aria-label="Text formatting"
value={format & IS_ITALIC ? 'on' : 'off'}
onValueChange={applyFormat.bind(null, 'italic')}
>
<ToolbarToggleItem value="on" aria-label="Italic">
</ToggleSingleGroupWithItem>
<ToggleSingleGroupWithItem
aria-label="Italic"
on={(currentFormat & IS_ITALIC) !== 0}
onValueChange={applyFormat.bind(null, 'italic')}
>
<ItalicIcon />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
<RadixToolbar.ToggleGroup
type="single"
aria-label="Text formatting"
value={format & IS_UNDERLINE ? 'on' : 'off'}
onValueChange={applyFormat.bind(null, 'underline')}
>
<ToolbarToggleItem value="on" aria-label="Underlined">
</ToggleSingleGroupWithItem>
<ToggleSingleGroupWithItem
aria-label="Underline"
className="[&_button]:rounded-r-md"
on={(currentFormat & IS_UNDERLINE) !== 0}
onValueChange={applyFormat.bind(null, 'underline')}
>
<UnderlinedIcon style={{ transform: 'translateY(2px)' }} />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
</ToggleSingleGroupWithItem>
</GroupGroup>

<ToolbarSeparator />
<RadixToolbar.ToggleGroup
type="single"
aria-label="Inline Code"
value={format & IS_CODE ? 'on' : 'off'}
onValueChange={applyFormat.bind(null, 'code')}
>
<ToolbarToggleItem value="on" aria-label="Inline Code">

<GroupGroup>
<ToggleSingleGroupWithItem
aria-label="Inline code"
className="[&_button]:rounded-md"
on={(currentFormat & IS_CODE) !== 0}
onValueChange={applyFormat.bind(null, 'code')}
>
<CodeIcon />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
</ToggleSingleGroupWithItem>
</GroupGroup>

<ToolbarSeparator />

<RadixToolbar.ToggleGroup
type="single"
aria-label="List type"
onValueChange={applyListType}
value={currentListType || ''}
onFocus={(e) => e.preventDefault()}
>
<ToolbarToggleItem value="bullet" aria-label="Bulleted list">
<BulletedListIcon />
</ToolbarToggleItem>
<ToolbarToggleItem value="number" aria-label="Numbered list">
<NumberedListIcon />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
<GroupGroup>
<ToggleSingleGroup
aria-label="List type"
onValueChange={applyListType}
value={currentListType || ''}
onFocus={(e) => e.preventDefault()}
>
<ToggleItem value="bullet" aria-label="Bulleted list" className="rounded-l-md">
<BulletedListIcon />
</ToggleItem>
<ToggleItem value="number" aria-label="Numbered list" className="rounded-r-md">
<NumberedListIcon />
</ToggleItem>
</ToggleSingleGroup>
</GroupGroup>

<ToolbarSeparator />
<BlockTypeSelect />
Expand All @@ -141,19 +145,19 @@ export const ToolbarPlugin = () => {
</ToolbarButton>

<ToolbarSeparator />
<RadixToolbar.ToggleGroup
type="single"
<ToggleSingleGroup
aria-label="View Mode"
onValueChange={(newViewMode) => setViewMode(ViewModeMap.get(newViewMode)!)}
value={viewMode === 'editor' ? '' : viewMode}
>
<ToolbarToggleItem value="diff" aria-label="View diff">
<ToggleItem value="diff" aria-label="View diff" className="rounded-l-md">
<DiffIcon />
</ToolbarToggleItem>
<ToolbarToggleItem value="markdown" aria-label="View Markdown">
</ToggleItem>

<ToggleItem value="markdown" aria-label="View Markdown" className="rounded-r-md">
<MarkdownIcon />
</ToolbarToggleItem>
</RadixToolbar.ToggleGroup>
</ToggleItem>
</ToggleSingleGroup>
</RadixToolbar.Root>
)
}
Expand All @@ -164,14 +168,41 @@ const ViewModeMap = new Map<string, ViewMode>([
['', 'editor'],
])

function ToolbarToggleItem(props: RadixToolbar.ToolbarToggleItemProps) {
return <RadixToolbar.ToggleItem {...props} className="" />
}
const ToggleItem = React.forwardRef<HTMLButtonElement, RadixToolbar.ToolbarToggleItemProps>(
({ className: passedClassName, ...props }, forwardedRef) => {
return <RadixToolbar.ToggleItem className={classnames(passedClassName, toggleItemClasses)} {...props} ref={forwardedRef} />
}
)

function ToolbarButton(props: RadixToolbar.ToolbarButtonProps) {
return <RadixToolbar.Button {...props} className="" />
}
const ToolbarButton = React.forwardRef<HTMLButtonElement, RadixToolbar.ToolbarButtonProps>((props, forwardedRef) => {
return <RadixToolbar.Button className={buttonClasses} {...props} ref={forwardedRef} />
})

function ToolbarSeparator() {
return <RadixToolbar.Separator className="" />
const ToggleSingleGroup = React.forwardRef<HTMLDivElement, Omit<RadixToolbar.ToolbarToggleGroupSingleProps, 'type'>>(
({ children, ...props }, forwardedRef) => {
return (
<RadixToolbar.ToggleGroup {...props} type="single" ref={forwardedRef}>
{children}
</RadixToolbar.ToggleGroup>
)
}
)

const ToggleSingleGroupWithItem = React.forwardRef<
HTMLDivElement,
Omit<RadixToolbar.ToolbarToggleGroupSingleProps, 'type'> & { on: boolean }
>(({ on, children, ...props }, forwardedRef) => {
return (
<ToggleSingleGroup {...props} value={on ? 'on' : 'off'} ref={forwardedRef}>
<ToggleItem value="on">{children}</ToggleItem>
</ToggleSingleGroup>
)
})

const GroupGroup: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return <div className="group flex flex-row gap-[1px] rounded-md">{children}</div>
}

const ToolbarSeparator = React.forwardRef<HTMLDivElement, RadixToolbar.SeparatorProps>(() => {
return <RadixToolbar.Separator className="mx-1" />
})
14 changes: 14 additions & 0 deletions src/ui/commonCssClasses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import classnames from 'classnames'

export const childSvgClasses =
'[&_svg]:transform [&_svg]:block [&_svg]:rotate-0 [&_svg]:skew-x-0 [&_svg]:skew-y-0 [&_svg]:scale-100 active:[&_svg]:translate-x-[1px] active:[&_svg]:translate-y-[1px]'

export const buttonClasses = classnames(
childSvgClasses,
'rounded-md border-0 bg-transparent p-2 transition-colors text-primary-900 hover:bg-primary-100 active:bg-primary-200 active:text-primary-800'
)

export const toggleItemClasses = classnames(
buttonClasses.replace('rounded-md', ''),
'data-toggle-on:bg-primary-200 data-toggle-on:text-primary-800'
)
2 changes: 1 addition & 1 deletion tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const config: Config = {
theme: {
extend: {
colors: {
primary: colors.sky,
primary: colors.slate,
blue: colors.blue,
surface: colors.slate,
transparent: colors.transparent,
Expand Down
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const externalPackages = [
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(IN_LADLE ? {} : { jsxRuntime: 'classic' }),
react(IN_LADLE ? {} : { jsxRuntime: 'classic' } as const),
dts({
rollupTypes: true,
compilerOptions: {
Expand Down

0 comments on commit adcdf97

Please sign in to comment.