-
Notifications
You must be signed in to change notification settings - Fork 112
feat: new toolbar style #120
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
base: main
Are you sure you want to change the base?
Conversation
fix: toolbar shadow style
Reviewer's GuideThis PR overhauls the editor selection toolbar UI and interactions: it upgrades dependencies, refactors core button and popover components to use Material-UI styling, introduces keyboard navigation for dropdown menus, and adds new toolbar actions (TurnInto, MoreOptions, ColorHighlight). File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
🥷 Ninja i18n – 🛎️ Translations need to be updatedProject
|
| lint rule | new reports | level | link |
|---|---|---|---|
| Missing translation | 237 | warning | contribute (via Fink 🐦) |
| Identical pattern | 3 | warning | contribute (via Fink 🐦) |
| Message without source | 1 | warning | contribute (via Fink 🐦) |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #120 +/- ##
=======================================
Coverage ? 58.35%
=======================================
Files ? 61
Lines ? 8078
Branches ? 453
=======================================
Hits ? 4714
Misses ? 3361
Partials ? 3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @lumixraku - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟡 General issues: 4 issues found
- 🟢 Testing: all looks good
- 🟡 Complexity: 2 issues found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
src/components/editor/components/toolbar/selection-toolbar/actions/Color.tsx
Outdated
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/ColorHighlight.tsx
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/ColorHighlight.tsx
Show resolved
Hide resolved
| }, | ||
| ]; | ||
|
|
||
| function TurnInfo() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting block option data, block detection logic, and menu rendering into separate modules and components to simplify TurnInfo.tsx.
Here are a few small, focused refactors that preserve every bit of functionality while cutting this file down to its essentials.
- Extract your block‐option data into
blockOptions.ts:
// src/components/SelectionToolbar/blockOptions.ts
import { FC, SVGProps } from 'react'
import {
ParagraphSvg, Heading1, Heading2, Heading3,
BulletedListSvg, NumberedListSvg,
ToggleListIcon, ToggleHeading1Icon, ToggleHeading2Icon, ToggleHeading3Icon,
QuoteSvg,
} from '@/assets/icons'
import { BlockType } from '@/application/types'
export type BlockOption = {
type: string
icon: FC<SVGProps<SVGSVGElement>>
label: string
blockType: BlockType
data?: any
group: 'text' | 'list' | 'toggle' | 'other'
}
export const blockOptions: BlockOption[] = [
{ type: 'paragraph', icon: ParagraphSvg, label: 'editor.text', blockType: BlockType.Paragraph, group: 'text' },
{ type: 'heading1', icon: Heading1, label: 'toolbar.h1', blockType: BlockType.HeadingBlock, data: { level: 1 }, group: 'text' },
// …the rest here
]- Pull out the “current block” detection & option‐filtering into a hook:
// src/components/SelectionToolbar/useTurnIntoOptions.ts
import { useSlateStatic } from 'slate-react'
import { getBlockEntry } from '@/application/slate-yjs/utils/editor'
import { blockOptions, BlockOption } from './blockOptions'
export function useTurnIntoOptions() {
const editor = useSlateStatic()
let currentGroup: BlockOption['group'] | null = null
let currentType = ''
let currentLevel: number | null = null
try {
const [node] = getBlockEntry(editor)
switch (node.type) {
case BlockType.Paragraph: currentType='paragraph'; currentGroup='text'; break
case BlockType.HeadingBlock:
currentType='heading'
currentLevel=(node.data as any).level
currentGroup='text'
break
// …the rest
}
} catch {}
const suggestions = blockOptions.filter(o =>
o.group === currentGroup && o.type !== `${currentType}${currentLevel || ''}`
)
const turnInto = blockOptions.filter(o => !suggestions.includes(o))
return { currentType, currentLevel, suggestions, turnInto }
}- Factor out a generic
<OptionsMenu>component to handle headers, MUI wiring, keyboard nav, etc.:
// src/components/SelectionToolbar/OptionsMenu.tsx
import { Menu, MenuItem, Typography } from '@mui/material'
import { useKeyboardNavigation } from '../hooks/useKeyboardNavigation'
export function OptionsMenu<T extends { type: string }>(props: {
anchorEl: HTMLElement | null
onClose(): void
groups: { label: string; options: T[] }[]
onSelect(opt: T): void
}) {
const open = Boolean(props.anchorEl)
const total = props.groups.reduce((sum, g) => sum + g.options.length, 0)
const { getButtonProps, selectedIndex } = useKeyboardNavigation({
itemCount: total, isOpen: open, onSelect: idx => {
let offset = 0
for (const group of props.groups) {
if (idx < offset + group.options.length) {
return props.onSelect(group.options[idx - offset])
}
offset += group.options.length
}
}, onClose: props.onClose
})
return (
<Menu anchorEl={props.anchorEl} open={open} onClose={props.onClose} /* …styles… */>
{props.groups.map((group, gIdx) => (
<div key={gIdx}>
<Typography variant="body2">{group.label}</Typography>
{group.options.map((opt, idx) => {
const globalIdx = props.groups
.slice(0, gIdx)
.reduce((s, g) => s + g.options.length, 0) + idx
return (
<MenuItem
key={opt.type}
ref={el => getButtonProps(globalIdx).ref?.(el as any)}
selected={selectedIndex === globalIdx}
sx={getButtonProps(globalIdx).sx}
onClick={() => props.onSelect(opt)}
>
<opt.icon /><span>{opt.label}</span>
{/** your checkmark logic still lives here **/}
</MenuItem>
)
})}
</div>
))}
</Menu>
)
}- Your
TurnInfo.tsxnow just orchestrates:
import { useState, useRef } from 'react'
import { ActionButton } from './ActionButton'
import { OptionsMenu } from './OptionsMenu'
import { useTurnIntoOptions } from './useTurnIntoOptions'
import { useTranslation } from 'react-i18next'
export default function TurnInfo() {
const { suggestions, turnInto, currentType, currentLevel } = useTurnIntoOptions()
const [anchorEl, setAnchorEl] = useState<HTMLElement|null>(null)
const ref = useRef<HTMLButtonElement>(null)
const { t } = useTranslation()
const handleSelect = (opt) => {
// … CustomEditor.turnToBlock logic …
setAnchorEl(null)
}
return (
<>
<ActionButton
ref={ref}
onClick={e => { e.preventDefault(); setAnchorEl(e.currentTarget) }}
tooltip={/* displayText(currentType, currentLevel) */ }
>
{/* label + icon */}
</ActionButton>
<OptionsMenu
anchorEl={anchorEl}
onClose={() => setAnchorEl(null)}
groups={[
{ label: t('toolbar.suggestions'), options: suggestions },
{ label: t('toolbar.turnInto'), options: turnInto }
]}
onSelect={handleSelect}
/>
</>
)
}These three extractions immediately cut TurnInfo.tsx by >70% while making each piece independently testable and reusable.
src/components/editor/components/toolbar/selection-toolbar/actions/TurnInto.tsx
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/TurnInto.tsx
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/TurnInto.tsx
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/TurnInto.tsx
Show resolved
Hide resolved
src/components/editor/components/toolbar/selection-toolbar/actions/TurnInto.tsx
Show resolved
Hide resolved
f29bcd8 to
2b45683
Compare
0e1d934 to
3e36ad0
Compare
3e36ad0 to
39b561e
Compare
5cfffab to
6e64f87
Compare
e44417c to
12dfeb0
Compare
Description
https://app-flowy-7s1lxq95t-lumixrakus-projects.vercel.app
Checklist
General
Testing
Feature-Specific
Summary by Sourcery
Revamp the editor’s selection toolbar with new transformation menus, enhanced styling, and keyboard navigation, while bumping dependencies and refining build/CI configurations.
New Features:
Enhancements:
Build:
CI:
startstep in web_coverage CI workflowChores: