Add joplin web article (#9)

This commit is contained in:
deytenit authored and GitHub committed 2026-03-20 01:32:26 +03:00
1 parent 90bf68c4c8
commit 575959ffa2
38 files changed
+1043 -554

No files matched your search

@@ -51,9 +51,6 @@ const MarkdownComponent = memo(function Markdown({ children, className }: Markdo
* <Markdown.H1>Title</Markdown.H1>
* <Markdown.P>Content goes here.</Markdown.P>
* </Markdown>
*
* // Or with Astro:
* <Content components={MARKDOWN_COMPONENTS} />
* ```
*/
export const Markdown = Object.assign(MarkdownComponent, {
@@ -24,7 +24,7 @@ import { MarkdownUL } from './MarkdownUL/MarkdownUL';
import type React from 'react';
/**
* A map of HTML tags to Markdown components for use with MDX or Astro Content.
* A map of HTML tags to Markdown components for use with MDX or other Markdown systems.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const MARKDOWN_COMPONENTS: Record<string, React.ComponentType<any>> = {
@@ -32,7 +32,7 @@ describe('PageHead', () => {
it('applies the correct classes for the strategy', () => {
render(<PageHead heading="Test" strategy="always-collapsed-fixed" />);
const header = screen.getByRole('banner');
expect(header).toHaveClass('fixed');
expect(header).toHaveClass('sticky');
expect(header).toHaveClass('shadow-md');
});
});
@@ -1,5 +1,5 @@
import { cn, useScroll, useResizeObserver } from '@ermnvldmr/stl';
import React, { type ReactNode, useRef, useEffect, useState } from 'react';
import { cn, useScroll } from '@ermnvldmr/stl';
import React, { type ReactNode, useEffect, useState } from 'react';
import { Header } from '../../Header/Header';
import { HStack } from '../../HStack/HStack';
@@ -68,8 +68,6 @@ export const PageHead = ({
}: PageHeadProps) => {
const { y: scrollY } = useScroll();
const [isCollapsed, setIsCollapsed] = useState(strategy.includes('always-collapsed'));
const headerRef = useRef<HTMLDivElement>(null);
const { height } = useResizeObserver(headerRef);
useEffect(() => {
if (strategy === 'collapsible-sticky') {
@@ -78,7 +76,7 @@ export const PageHead = ({
}, [scrollY, strategy]);
const rootClasses = cn(
'page-head w-full transition-all duration-200 bg-[var(--rb-background)] fixed top-0 z-10 border-b border-[var(--rb-outline)]/10',
'page-head w-full transition-all duration-200 bg-[var(--rb-background)] sticky top-0 z-10 border-b border-[var(--rb-outline)]/10',
{
'shadow-md bg-[var(--rb-background)]/90 backdrop-blur-md': isCollapsed,
},
@@ -124,28 +122,25 @@ export const PageHead = ({
);
return (
<>
<header ref={headerRef} className={rootClasses}>
<div
className={cn(
'grid transition-[grid-template-rows] duration-300 ease-in-out',
isCollapsed ? 'grid-rows-[0fr]' : 'grid-rows-[1fr]'
)}
inert={isCollapsed || undefined}
>
<div className="overflow-hidden">{expandedContent}</div>
</div>
<div
className={cn(
'grid transition-[grid-template-rows] duration-300 ease-in-out',
isCollapsed ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'
)}
inert={!isCollapsed || undefined}
>
<div className="overflow-hidden">{collapsedContent}</div>
</div>
</header>
<div style={{ height }} />
</>
<header className={rootClasses}>
<div
className={cn(
'grid transition-[grid-template-rows] duration-300 ease-in-out',
isCollapsed ? 'grid-rows-[0fr]' : 'grid-rows-[1fr]'
)}
inert={isCollapsed || undefined}
>
<div className="overflow-hidden">{expandedContent}</div>
</div>
<div
className={cn(
'grid transition-[grid-template-rows] duration-300 ease-in-out',
isCollapsed ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'
)}
inert={!isCollapsed || undefined}
>
<div className="overflow-hidden">{collapsedContent}</div>
</div>
</header>
);
};
+25 -5
View File
@@ -132,29 +132,49 @@ describe('components/Text', () => {
// TDD: fails before implementation (old code uses text-[14px], not text-rb-body-m)
it('applies text-rb-{type}-{size} class', () => {
render(<Text size="m" type="body">Content</Text>);
render(
<Text size="m" type="body">
Content
</Text>
);
expect(screen.getByText('Content')).toHaveClass('text-rb-body-m');
});
it('does not apply legacy px-based font-size classes', () => {
render(<Text size="m" type="body">Content</Text>);
render(
<Text size="m" type="body">
Content
</Text>
);
expect(screen.getByText('Content')).not.toHaveClass('text-[14px]');
expect(screen.getByText('Content')).not.toHaveClass('leading-[20px]');
});
// Regression guards: pass before and after
it('applies font-medium for label type', () => {
render(<Text size="m" type="label">Label</Text>);
render(
<Text size="m" type="label">
Label
</Text>
);
expect(screen.getByText('Label')).toHaveClass('font-medium');
});
it('applies font-sans for body type', () => {
render(<Text size="m" type="body">Body</Text>);
render(
<Text size="m" type="body">
Body
</Text>
);
expect(screen.getByText('Body')).toHaveClass('font-sans');
});
it('applies font-serif for display type', () => {
render(<Text size="l" type="display">Display</Text>);
render(
<Text size="l" type="display">
Display
</Text>
);
expect(screen.getByText('Display')).toHaveClass('font-serif');
});
});
+13 -1
View File
@@ -119,7 +119,19 @@ const TextComponent = forwardRef<HTMLElement, TextProps>(function Text(
{...props}
ref={internalRef}
className={cn(
getTypographyClassNames({ type, size, color, bold, italic, underline, strike, align, wrap, overflow, maxLines }),
getTypographyClassNames({
type,
size,
color,
bold,
italic,
underline,
strike,
align,
wrap,
overflow,
maxLines,
}),
delay !== undefined &&
(isVisible
? 'animate-in fade-in slide-in-from-bottom-2 duration-1000 ease-out'