Replace most stylesheets with tailwind styles

This commit is contained in:
Alejandro Celaya 2025-04-03 10:46:32 +02:00
parent aefe5e0848
commit fd40e2b7bc
11 changed files with 39 additions and 91 deletions

View File

@ -1,22 +0,0 @@
.main-header.main-header {
color: white;
background-color: var(--brand-color) !important;
.navbar-brand {
color: inherit !important;
}
}
.main-header__brand-logo {
width: 26px;
margin-right: 5px;
}
.main-header__toggle-icon {
width: 20px;
transition: transform 300ms;
}
.main-header__toggle-icon--opened {
transform: rotate(180deg);
}

View File

@ -9,7 +9,6 @@ import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } f
import type { FCWithDeps } from '../container/utils';
import { componentFactory, useDependencies } from '../container/utils';
import { ShlinkLogo } from './img/ShlinkLogo';
import './MainHeader.scss';
type MainHeaderDeps = {
ServersDropdown: FC;
@ -25,20 +24,22 @@ const MainHeader: FCWithDeps<unknown, MainHeaderDeps> = () => {
useEffect(collapse, [location, collapse]);
const settingsPath = '/settings';
const toggleClass = clsx('main-header__toggle-icon', { 'main-header__toggle-icon--opened': isNotCollapsed });
return (
<Navbar color="primary" dark fixed="top" className="main-header" expand="md">
<Navbar color="primary" dark fixed="top" expand="md" className="tw:text-white tw:bg-lm-brand tw:dark:bg-dm-brand">
<NavbarBrand tag={Link} to="/">
<ShlinkLogo className="main-header__brand-logo tw:inline" color="white" /> Shlink
<ShlinkLogo className="tw:inline tw:w-7 tw:mr-1" color="white" /> Shlink
</NavbarBrand>
<NavbarToggler onClick={toggleCollapse}>
<FontAwesomeIcon icon={arrowIcon} className={toggleClass} />
<FontAwesomeIcon
icon={arrowIcon}
className={clsx('tw:transition-transform tw:duration-300', { 'tw:rotate-180': isNotCollapsed })}
/>
</NavbarToggler>
<Collapse navbar isOpen={isNotCollapsed}>
<Nav navbar className="ms-auto">
<Nav navbar className="tw:ml-auto">
<NavItem>
<NavLink tag={Link} to={settingsPath} active={pathname.startsWith(settingsPath)}>
<FontAwesomeIcon icon={cogsIcon} />&nbsp; Settings

View File

@ -1,9 +0,0 @@
@use '../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.shlink-versions-container--with-sidebar {
margin-left: 0;
@media (min-width: base.$mdMin) {
margin-left: base.$asideMenuWidth;
}
}

View File

@ -2,7 +2,6 @@ import { clsx } from 'clsx';
import type { SelectedServer } from '../servers/data';
import { isReachableServer } from '../servers/data';
import { ShlinkVersions } from './ShlinkVersions';
import './ShlinkVersionsContainer.scss';
export type ShlinkVersionsContainerProps = {
selectedServer: SelectedServer;
@ -10,9 +9,7 @@ export type ShlinkVersionsContainerProps = {
export const ShlinkVersionsContainer = ({ selectedServer }: ShlinkVersionsContainerProps) => (
<div
className={clsx('text-center', {
'shlink-versions-container--with-sidebar': isReachableServer(selectedServer),
})}
className={clsx('text-center', { 'tw:md:ml-(--aside-menu-width)': isReachableServer(selectedServer) })}
>
<ShlinkVersions selectedServer={selectedServer} />
</div>

View File

@ -1,17 +0,0 @@
@use '../../../node_modules/@shlinkio/shlink-frontend-kit/dist/base';
.server-error__container {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.server-error__delete-btn {
color: base.$dangerColor;
font-weight: inherit;
}
.server-error__delete-btn:hover {
text-decoration: underline;
}

View File

@ -8,7 +8,6 @@ import type { SelectedServer, ServersMap } from '../data';
import { isServerWithId } from '../data';
import type { DeleteServerButtonProps } from '../DeleteServerButton';
import { ServersListGroup } from '../ServersListGroup';
import './ServerError.scss';
type ServerErrorProps = {
servers: ServersMap;
@ -24,8 +23,8 @@ const ServerError: FCWithDeps<ServerErrorProps, ServerErrorDeps> = ({ servers, s
return (
<NoMenuLayout>
<div className="server-error__container flex-column">
<Message className="w-100 mb-3 mb-md-5" variant="error">
<div className="tw:flex tw:flex-col tw:items-center tw:gap-y-4 tw:md:gap-y-8">
<Message className="tw:w-full tw:lg:w-[80%]" variant="error">
{!isServerWithId(selectedServer) && 'Could not find this Shlink server.'}
{isServerWithId(selectedServer) && (
<>
@ -39,19 +38,17 @@ const ServerError: FCWithDeps<ServerErrorProps, ServerErrorDeps> = ({ servers, s
These are the Shlink servers currently configured. Choose one of
them or <Link to="/server/create">add a new one</Link>.
</p>
<Card className="tw:w-full tw:max-w-100 tw:overflow-hidden tw:mt-4">
<Card className="tw:w-full tw:max-w-100 tw:overflow-hidden">
<ServersListGroup borderless servers={Object.values(servers)} />
</Card>
{isServerWithId(selectedServer) && (
<div className="container mt-3 mt-md-5">
<p className="tw:text-xl">
Alternatively, if you think you may have misconfigured this server, you
can <DeleteServerButton server={selectedServer} className="server-error__delete-btn">remove
it</DeleteServerButton> or&nbsp;
<Link to={`/server/${selectedServer.id}/edit?reconnect=true`}>edit it</Link>.
</p>
</div>
<p className="tw:text-xl">
Alternatively, if you think you may have misconfigured this server, you
can <DeleteServerButton server={selectedServer} className="tw:text-danger tw:hover:underline">remove
it</DeleteServerButton> or&nbsp;
<Link to={`/server/${selectedServer.id}/edit?reconnect=true`}>edit it</Link>.
</p>
)}
</div>
</NoMenuLayout>

View File

@ -14,3 +14,11 @@
border-radius: .5rem;
}
}
@layer base {
:root {
--header-height: 56px;
/* Width of ShlinkWebComponent's side menu when not collapsed */
--aside-menu-width: 260px;
}
}

View File

@ -1,5 +0,0 @@
@mixin horizontal-align {
position: absolute;
left: 50%;
transform: translateX(-50%);
}

View File

@ -1,5 +0,0 @@
@mixin vertical-align($extraTransforms: null) {
position: absolute;
top: 50%;
transform: translateY(-50%) $extraTransforms;
}

View File

@ -51,14 +51,12 @@ describe('<MainHeader />', () => {
const toggle = screen.getByLabelText('Toggle navigation');
const icon = toggle.firstChild;
expect(icon).toHaveAttribute('class', expect.stringMatching(/main-header__toggle-icon$/));
expect(icon).not.toHaveClass('tw:rotate-180');
await user.click(toggle);
expect(icon).toHaveAttribute(
'class',
expect.stringMatching(/main-header__toggle-icon main-header__toggle-icon--opened$/),
);
expect(icon).toHaveClass('tw:rotate-180');
await user.click(toggle);
expect(icon).toHaveAttribute('class', expect.stringMatching(/main-header__toggle-icon$/));
expect(icon).not.toHaveClass('tw:rotate-180');
});
it('opens Collapse when clicking toggle', async () => {

View File

@ -16,11 +16,16 @@ describe('<ShlinkVersionsContainer />', () => {
])('passes a11y checks', (selectedServer) => checkAccessibility(setUp(selectedServer)));
it.each([
[null, 'text-center'],
[fromPartial<SelectedServer>({}), 'text-center'],
[fromPartial<ReachableServer>({ version: '1.0.0' }), 'text-center shlink-versions-container--with-sidebar'],
])('renders proper col classes based on sidebar status', (selectedServer, expectedClasses) => {
[null, false],
[fromPartial<SelectedServer>({}), false],
[fromPartial<ReachableServer>({ version: '1.0.0' }), true],
])('renders proper col classes based on sidebar status', (selectedServer, shouldAddMargin) => {
const { container } = setUp(selectedServer);
expect(container.firstChild).toHaveAttribute('class', `${expectedClasses}`);
if (shouldAddMargin) {
expect(container.firstChild).toHaveClass('tw:md:ml-(--aside-menu-width)');
} else {
expect(container.firstChild).not.toHaveClass('tw:md:ml-(--aside-menu-width)');
}
});
});