pl-fe: more migrations away from tailwind

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-15 18:26:25 +02:00
parent 693b507267
commit ef7d47a237
7 changed files with 92 additions and 44 deletions

View File

@ -51,6 +51,7 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
const [tokenStart, setTokenStart] = useState<number | null>(0);
const inputRef = useRef<HTMLInputElement>(null);
const suggestionsRef = useRef<HTMLUListElement>(null);
const onChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
const [tokenStart, token] = textAtCursorMatchesToken(
@ -110,7 +111,7 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
case 'ArrowUp':
if (!suggestionsHidden && (suggestions.length > 0 || menu)) {
e.preventDefault();
setSelectedSuggestion((selectedSuggestion) => Math.min(selectedSuggestion - 1, lastIndex));
setSelectedSuggestion((selectedSuggestion) => Math.max(selectedSuggestion - 1, 0));
}
break;
@ -184,9 +185,8 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
key={key}
data-index={i}
className={clsx({
'px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 focus:bg-gray-100 dark:focus:bg-primary-800 group': true,
'hover:bg-gray-100 dark:hover:bg-gray-800': i !== selectedSuggestion,
'bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800': i === selectedSuggestion,
'⁂-autosuggest-suggestions__item': true,
'⁂-autosuggest-suggestions__item--selected': i === selectedSuggestion,
})}
onMouseDown={onSuggestionClick}
onTouchEnd={onSuggestionClick}
@ -209,7 +209,7 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
};
const renderMenu = () => {
const { menu, suggestions } = props;
const { menu } = props;
if (!menu) {
return null;
@ -217,9 +217,7 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
return menu.map((item, i) => (
<a
className={clsx('flex cursor-pointer items-center space-x-2 px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-100 focus:bg-gray-100 dark:text-gray-500 dark:hover:bg-gray-800 dark:focus:bg-primary-800', {
selected: suggestions.length - selectedSuggestion === i,
})}
className={'⁂-autosuggest-suggestions__menu-item'}
href='#'
role='button'
tabIndex={0}
@ -277,14 +275,13 @@ const AutosuggestInput: React.FC<IAutosuggestInput> = ({
<div
style={setPortalPosition()}
className={clsx({
'fixed w-full z-[1001] shadow bg-white dark:bg-gray-900 rounded-lg py-1 dark:ring-2 dark:ring-primary-700 focus:outline-none': true,
hidden: !visible,
block: visible,
'⁂-autosuggest-suggestions': true,
'⁂-autosuggest-suggestions--visible': visible,
})}
>
<div className='space-y-0.5'>
<ul className='⁂-autosuggest-suggestions__items' ref={suggestionsRef}>
{props.suggestions.map(renderSuggestion)}
</div>
</ul>
{renderMenu()}
</div>

View File

@ -223,7 +223,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
}),
size({
apply: ({ availableHeight, elements }) => {
elements.floating.style.maxHeight = `${Math.max(50, availableHeight - 12)}px`;
elements.floating.style.maxHeight = `${Math.max(50, availableHeight - 8)}px`;
},
}),
],
@ -344,8 +344,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
}
const getClassName = () => {
const className = clsx('z-[1001] bg-white py-1 shadow-lg ease-in-out focus:outline-none black:bg-black no-reduce-motion:transition-all dark:bg-gray-900 dark:ring-2 dark:ring-primary-700', {
'rounded-md min-w-56 max-w-sm duration-100': true,
const className = clsx('', {
'no-reduce-motion:scale-0': !(isDisplayed && isOpen),
'scale-100': isDisplayed && isOpen,
'origin-bottom': placement === 'top',
@ -383,7 +382,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
<div
data-testid='dropdown-menu'
ref={refs.setFloating}
className='z-[1001] flex'
className='⁂-dropdown-menu'
style={{
position: strategy,
top: y ?? 0,
@ -397,7 +396,7 @@ const DropdownMenu = (props: IDropdownMenu) => {
<div
ref={arrowRef}
style={arrowProps}
className='pointer-events-none absolute z-[-1] size-3 bg-white black:bg-black dark:bg-gray-900'
className='⁂-dropdown-menu__arrow'
/>
</div>
</div>

View File

@ -4,7 +4,6 @@ import React, { useState, useEffect, useCallback } from 'react';
import { useIntl, MessageDescriptor } from 'react-intl';
import Icon from 'pl-fe/components/ui/icon';
import Text from 'pl-fe/components/ui/text';
import { useSettings } from 'pl-fe/hooks/use-settings';
interface IScrollTopButton {
@ -81,26 +80,15 @@ const ScrollTopButton: React.FC<IScrollTopButton> = ({
return (
<div
className={clsx(
'fixed left-1/2 z-50 -translate-x-1/2 transition-all', {
'top-2 opacity-100': visible,
'-top-4 opacity-0': !visible,
})}
className={clsx('⁂-scroll-top-button', { '⁂-scroll-top-button--visible': visible })}
aria-hidden={!visible}
>
<button
className='flex cursor-pointer items-center space-x-1.5 whitespace-nowrap rounded-full bg-primary-600/80 px-4 py-2 text-white backdrop-blur-md transition-transform hover:scale-105 hover:bg-primary-700/80 active:scale-100'
onClick={handleClick}
tabIndex={visible ? 0 : -1}
>
<Icon
className='size-4'
src={require('@phosphor-icons/core/regular/arrow-line-up.svg')}
/>
<button onClick={handleClick} tabIndex={visible ? 0 : -1}>
<Icon src={require('@phosphor-icons/core/regular/arrow-line-up.svg')} />
<Text theme='inherit' size='sm'>
<p>
{intl.formatMessage(message, { count })}
</Text>
</p>
</button>
</div>
);

View File

@ -37,7 +37,7 @@ const SitePreview: React.FC<ISitePreview> = ({ plFe }) => {
return (
<div className={bodyClass}>
<InlineStyle>{`.site-preview {${themeCss}}`}</InlineStyle>
<BackgroundShapes position='absolute' hidden={userTheme === 'black'} />
<BackgroundShapes preview hidden={userTheme === 'black'} />
<div className='absolute z-[2] self-center overflow-hidden rounded-lg bg-accent-500 p-2 text-white'>
<FormattedMessage id='site_preview.preview' defaultMessage='Preview' />

View File

@ -3,19 +3,15 @@ import React from 'react';
interface IBackgroundShapes {
/** Whether the shapes should be absolute positioned or fixed. */
position?: 'fixed' | 'absolute';
preview?: boolean;
/** Override visibility. */
hidden?: boolean;
}
/** Gradient that appears in the background of the UI. */
const BackgroundShapes: React.FC<IBackgroundShapes> = ({ position = 'fixed', hidden }) => hidden ? null : (
<div
className={clsx(position, 'pointer-events-none inset-x-0 top-0 flex justify-center overflow-hidden ', {
'black:hidden': hidden === undefined,
})}
>
<div className='bg-gradient-sm lg:bg-gradient-light lg:dark:bg-gradient-dark h-screen w-screen' />
const BackgroundShapes: React.FC<IBackgroundShapes> = ({ preview, hidden }) => hidden ? null : (
<div className={clsx('⁂-background-shapes', preview && '⁂-background-shapes--preview')}>
<div />
</div>
);

View File

@ -172,6 +172,62 @@ a.⁂-list-item,
overflow: hidden;
}
.-scroll-top-button {
@apply fixed left-1/2 z-50 -translate-x-1/2 transition-all -top-4 opacity-0;
&--visible {
@apply top-2 opacity-100;
}
button {
@apply flex cursor-pointer items-center space-x-1.5 whitespace-nowrap rounded-full bg-primary-600/80 px-4 py-2 text-white backdrop-blur-md transition-transform hover:scale-105 hover:bg-primary-700/80 active:scale-100;
.-icon svg {
@apply size-4;
}
p {
@include mixins.text($theme: inherit, $size: sm);
}
}
}
.-dropdown-menu {
@apply z-[1001] flex;
> div {
@apply z-[1001] bg-white py-1 shadow-lg ease-in-out focus:outline-none black:bg-black no-reduce-motion:transition-all dark:bg-gray-900 dark:ring-2 dark:ring-primary-700 rounded-md min-w-56 max-w-sm duration-100;
}
&__arrow {
@apply pointer-events-none absolute z-[-1] size-3 bg-white black:bg-black dark:bg-gray-900;
}
}
.-autosuggest-suggestions {
@apply fixed w-full z-[1001] shadow bg-white dark:bg-gray-900 rounded-lg py-1 dark:ring-2 dark:ring-primary-700 focus:outline-none hidden;
&--visible, &:focus-within {
@apply block;
}
&__items {
@apply space-y-0.5;
}
&__item {
@apply px-4 py-2.5 text-sm text-gray-700 dark:text-gray-500 focus:bg-gray-100 dark:focus:bg-primary-800 hover:bg-gray-100 dark:hover:bg-gray-800;
&--selected {
@apply bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800;
}
}
&__menu-item {
@apply flex cursor-pointer items-center space-x-2 px-4 py-2.5 text-sm text-gray-700 hover:bg-gray-100 focus:bg-gray-100 dark:text-gray-500 dark:hover:bg-gray-800 dark:focus:bg-primary-800;
}
}
div[data-viewport-type="window"]:has(.-empty-message) {
position: initial!important;
}

View File

@ -271,4 +271,16 @@ body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.-background-shapes {
@apply fixed pointer-events-none inset-x-0 top-0 flex justify-center overflow-hidden black:hidden;
&--preview {
@apply absolute;
}
> div {
@apply bg-gradient-sm lg:bg-gradient-light lg:dark:bg-gradient-dark h-screen w-screen;
}
}