fixed many css issues

This commit is contained in:
Nate Kelley 2025-09-13 18:13:00 -06:00
parent d4487e98f7
commit e0a8ee490c
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
7 changed files with 100 additions and 29 deletions

View File

@ -27,7 +27,8 @@
"useExhaustiveDependencies": "off",
"noChildrenProp": "off",
"useUniqueElementIds": "off",
"useParseIntRadix": "off"
"useParseIntRadix": "off",
"noUnusedFunctionParameters": "warn"
},
"style": {
"noNonNullAssertion": "error",
@ -84,6 +85,12 @@
"linter": {
"enabled": false
}
},
{
"includes": ["**/*.css"],
"linter": {
"enabled": false
}
}
],
"formatter": {
@ -102,5 +109,10 @@
"semicolons": "always",
"arrowParentheses": "always"
}
},
"css": {
"parser": {
"cssModules": true
}
}
}

View File

@ -1,29 +1,58 @@
import { Mention } from '@tiptap/extension-mention';
import { Mention, type MentionNodeAttrs } from '@tiptap/extension-mention';
import { ReactNodeViewRenderer } from '@tiptap/react';
import type { SuggestionOptions } from '@tiptap/suggestion';
import { createMentionSuggestionExtension } from './createMentionSuggestionOption';
import { MentionPill } from './MentionPill';
import type { MentionInputTriggerItem } from './MentionInput.types';
import { MentionPill, type MentionPillAttributes } from './MentionPill';
// Store items with popover content
const mentionItems: MentionInputTriggerItem[] = [
{
value: 'Lea Thompson',
label: 'Lea Thompson',
popoverContent: ({ label }) => <div>Popover for {label}</div>,
},
{
value: 'Cyndi Lauper',
label: 'Cyndi Lauper',
popoverContent: ({ label }) => <div>Artist info for {label}</div>,
},
{
value: 'Tom Cruise',
label: 'Tom Cruise',
popoverContent: ({ label }) => <div>Actor details for {label}</div>,
},
{
value: 'Madonna',
label: 'Madonna',
popoverContent: ({ label }) => <div>Icon info for {label}</div>,
},
];
const atSuggestion = createMentionSuggestionExtension({
trigger: '@',
items: [
{ value: 'Lea Thompson', label: 'Lea Thompson' },
{ value: 'Cyndi Lauper', label: 'Cyndi Lauper' },
{ value: 'Tom Cruise', label: 'Tom Cruise' },
{ value: 'Madonna', label: 'Madonna' },
],
items: mentionItems,
});
export const MentionExtension = Mention.extend({
addNodeView() {
return ReactNodeViewRenderer(MentionPill, { as: 'span' });
},
addAttributes() {
addStorage() {
return {
label: { default: '' },
value: { default: '' },
mentionItems, // Store the items with popover content
};
},
addAttributes() {
return {
label: '',
value: '',
} satisfies MentionPillAttributes;
},
}).configure({
suggestions: [atSuggestion],
suggestions: [atSuggestion] as Omit<
SuggestionOptions<MentionInputTriggerItem, MentionNodeAttrs>,
'editor'
>[],
deleteTriggerWithBackspace: true,
});

View File

@ -11,10 +11,9 @@ export const MentionInput = () => {
extensions: [Document, Paragraph, Text, MentionExtension],
content: '',
autofocus: true,
editable: true,
editorProps: {
attributes: {
class: 'p-1 swag',
class: 'p-1',
},
},
});

View File

@ -1,4 +1,5 @@
import type { MentionOptions } from '@tiptap/extension-mention';
import type { MentionNodeAttrs, MentionOptions } from '@tiptap/extension-mention';
import type { MentionPillAttributes } from './MentionPill';
export type MentionOnSelectParams = Pick<
MentionTriggerItem,
@ -17,6 +18,8 @@ export type MentionTriggerItem<T = string> = {
type?: 'item';
selected?: boolean;
doNotAddPipeOnSelect?: boolean;
//options for the pill
popoverContent?: (props: Pick<MentionTriggerItem, 'value' | 'label'>) => React.ReactNode;
};
export type MentionInputTriggerGroup<T = string> = {
@ -48,4 +51,7 @@ export type MentionInputProps = {
//The tip tap type for a suggestion
export type MentionSuggestionExtension = MentionOptions<MentionInputTriggerItem>['suggestion'];
export type MentionSuggestionExtension = MentionOptions<
MentionInputTriggerItem,
MentionPillAttributes & MentionNodeAttrs
>['suggestion'];

View File

@ -1,14 +1,42 @@
import { NodeViewWrapper, type ReactNodeViewProps } from '@tiptap/react';
import { useState } from 'react';
import type { MentionTriggerItem } from './MentionInput.types';
export const MentionPill = ({ node }: ReactNodeViewProps<MentionTriggerItem>) => {
console.log(node);
export type MentionPillAttributes = Pick<
MentionTriggerItem,
'label' | 'value' | 'doNotAddPipeOnSelect'
>;
export const MentionPill = ({ node, extension }: ReactNodeViewProps<MentionTriggerItem>) => {
const attrs = node.attrs as MentionPillAttributes;
const [showPopover, setShowPopover] = useState(false);
// Access the mention items from extension storage
const mentionItems = extension.storage.mentionItems as MentionTriggerItem[];
// Find the matching item with popover content
const matchingItem = mentionItems.find((item) => item.value === attrs.value);
const popoverContent = matchingItem?.popoverContent?.({
value: attrs.value,
label: attrs.label,
});
return (
<NodeViewWrapper as={node.attrs.as ?? 'span'}>
<span className="bg-item-select border rounded p-0.5 w-fit">
<label>{node.attrs.label}</label>
<span
className="bg-item-select border rounded p-0.5 w-fit cursor-pointer hover:bg-opacity-80"
onMouseEnter={() => setShowPopover(true)}
onMouseLeave={() => setShowPopover(false)}
>
{node.attrs.label}
</span>
{/* Render popover if content exists */}
{showPopover && popoverContent && (
<div className="absolute z-50 bg-white border rounded shadow-lg p-2 mt-1">
{popoverContent}
</div>
)}
</NodeViewWrapper>
);
};

View File

@ -1,10 +1,6 @@
import { posToDOMRect, ReactRenderer } from '@tiptap/react';
import { defaultQueryMentionsFilter } from './defaultQueryMentionsFilter';
import type {
MentionInputTriggerItem,
MentionSuggestionExtension,
MentionTriggerItem,
} from './MentionInput.types';
import type { MentionInputTriggerItem, MentionSuggestionExtension } from './MentionInput.types';
import {
MentionList,
type MentionListImperativeHandle,
@ -18,7 +14,7 @@ export const createMentionSuggestionExtension = ({
trigger: string;
items: MentionInputTriggerItem[] | ((props: { query: string }) => MentionInputTriggerItem[]); //if no function is provided we will use a literal string match
}): MentionSuggestionExtension => ({
char: '@',
char: trigger,
items:
typeof items === 'function' ? items : ({ query }) => defaultQueryMentionsFilter(query, items),
render: () => {
@ -75,7 +71,8 @@ export const createMentionSuggestionExtension = ({
},
command: ({ editor, props, range }) => {
console.log(props);
const doNotAddPipeOnSelect = props.doNotAddPipeOnSelect ?? false;
if (doNotAddPipeOnSelect) return;
editor
.chain()
.focus()

View File

@ -29,5 +29,5 @@
text-align: right;
color: var(--color-text-tertiary);
user-select: none;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-family: "Consolas", "Monaco", "Courier New", monospace;
}