UI Components Medium
RTL Layout
Complete right-to-left layout with sidebar, navigation and content area using CSS logical properties for seamless LTR/RTL switching.
Open in Lab
MCP
css
Targets: JS HTML
Code
/* ── Reset & Base ── */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg-primary: #0a0a0a;
--bg-secondary: #111111;
--bg-tertiary: #1a1a1a;
--bg-card: #141414;
--border: #252525;
--border-light: #333333;
--text-primary: #f0f0f0;
--text-secondary: #999999;
--text-muted: #666666;
--accent-blue: #3b82f6;
--accent-green: #22c55e;
--accent-amber: #f59e0b;
--accent-red: #ef4444;
--radius: 10px;
--sidebar-width: 260px;
--topbar-height: 60px;
}
html {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.5;
}
body {
min-height: 100vh;
}
button {
font: inherit;
cursor: pointer;
border: none;
background: none;
color: inherit;
}
a {
color: inherit;
text-decoration: none;
}
ul {
list-style: none;
}
/* ── App shell ── */
.app-shell {
display: flex;
min-height: 100vh;
}
/* ── Sidebar ── */
.sidebar {
position: fixed;
inset-block-start: 0;
inset-inline-start: 0;
inline-size: var(--sidebar-width);
block-size: 100vh;
background: var(--bg-secondary);
border-inline-end: 1px solid var(--border);
display: flex;
flex-direction: column;
z-index: 100;
transition: transform 0.3s ease;
}
.sidebar.collapsed {
transform: translateX(-100%);
}
[dir="rtl"] .sidebar.collapsed {
transform: translateX(100%);
}
.sidebar-header {
display: flex;
align-items: center;
gap: 12px;
padding-block: 20px;
padding-inline: 20px;
border-block-end: 1px solid var(--border);
}
.sidebar-logo {
font-size: 1.5rem;
color: var(--accent-blue);
}
.sidebar-brand {
font-size: 1.1rem;
font-weight: 600;
letter-spacing: 0.02em;
}
.sidebar-nav {
flex: 1;
padding-block: 16px;
padding-inline: 12px;
display: flex;
flex-direction: column;
gap: 4px;
}
.nav-link {
display: flex;
align-items: center;
gap: 12px;
padding-block: 10px;
padding-inline: 14px;
border-radius: 8px;
font-size: 0.9rem;
color: var(--text-secondary);
transition: all 0.2s;
}
.nav-link:hover {
background: var(--bg-tertiary);
color: var(--text-primary);
}
.nav-link.active {
background: rgba(59, 130, 246, 0.12);
color: var(--accent-blue);
}
.nav-icon {
font-size: 1.1rem;
inline-size: 24px;
text-align: center;
}
.sidebar-footer {
padding-block: 16px;
padding-inline: 16px;
border-block-start: 1px solid var(--border);
}
.user-badge {
display: flex;
align-items: center;
gap: 12px;
}
.user-avatar {
inline-size: 36px;
block-size: 36px;
border-radius: 50%;
background: var(--accent-blue);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
font-weight: 600;
}
.user-info {
display: flex;
flex-direction: column;
}
.user-name {
font-size: 0.85rem;
font-weight: 500;
}
.user-role {
font-size: 0.75rem;
color: var(--text-muted);
}
/* ── Main area ── */
.main-area {
flex: 1;
margin-inline-start: var(--sidebar-width);
transition: margin-inline-start 0.3s ease;
}
.main-area.expanded {
margin-inline-start: 0;
}
/* ── Topbar ── */
.topbar {
position: sticky;
inset-block-start: 0;
display: flex;
align-items: center;
justify-content: space-between;
block-size: var(--topbar-height);
padding-inline: 24px;
background: var(--bg-primary);
border-block-end: 1px solid var(--border);
z-index: 50;
}
.topbar-start,
.topbar-end {
display: flex;
align-items: center;
gap: 12px;
}
.sidebar-toggle {
font-size: 1.2rem;
padding: 6px;
border-radius: 6px;
color: var(--text-secondary);
}
.sidebar-toggle:hover {
background: var(--bg-tertiary);
}
.page-title {
font-size: 1.1rem;
font-weight: 600;
}
.dir-toggle {
display: flex;
align-items: center;
gap: 8px;
padding-block: 6px;
padding-inline: 14px;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 0.85rem;
font-weight: 500;
color: var(--accent-blue);
transition: background 0.2s;
}
.dir-toggle:hover {
background: var(--bg-card);
}
.icon-btn {
padding: 8px;
border-radius: 8px;
font-size: 1.1rem;
color: var(--text-secondary);
}
.icon-btn:hover {
background: var(--bg-tertiary);
}
/* ── Content ── */
.content {
padding-block: 24px;
padding-inline: 24px;
}
/* Stats row */
.stats-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-block-end: 24px;
}
.stat-card {
display: flex;
align-items: center;
gap: 16px;
padding-block: 20px;
padding-inline: 20px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
}
.stat-icon {
inline-size: 48px;
block-size: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.4rem;
flex-shrink: 0;
}
.stat-icon.blue {
background: rgba(59, 130, 246, 0.15);
}
.stat-icon.green {
background: rgba(34, 197, 94, 0.15);
}
.stat-icon.amber {
background: rgba(245, 158, 11, 0.15);
}
.stat-icon.red {
background: rgba(239, 68, 68, 0.15);
}
.stat-body {
display: flex;
flex-direction: column;
}
.stat-value {
font-size: 1.4rem;
font-weight: 700;
}
.stat-label {
font-size: 0.8rem;
color: var(--text-muted);
}
/* Card grid */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 16px;
}
.card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding-block: 20px;
padding-inline: 20px;
}
.card-wide {
grid-column: 1 / -1;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-block-end: 16px;
}
.card-title {
font-size: 1rem;
font-weight: 600;
}
.card-action {
font-size: 0.8rem;
color: var(--accent-blue);
}
.card-action:hover {
text-decoration: underline;
}
/* Activity list */
.activity-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.activity-item {
display: flex;
align-items: center;
gap: 12px;
padding-block: 10px;
padding-inline: 12px;
background: var(--bg-tertiary);
border-radius: 8px;
}
.activity-dot {
inline-size: 8px;
block-size: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.activity-dot.green {
background: var(--accent-green);
}
.activity-dot.blue {
background: var(--accent-blue);
}
.activity-dot.amber {
background: var(--accent-amber);
}
.activity-dot.red {
background: var(--accent-red);
}
.activity-text {
flex: 1;
font-size: 0.85rem;
color: var(--text-secondary);
}
.activity-time {
font-size: 0.75rem;
color: var(--text-muted);
white-space: nowrap;
}
/* Quick actions */
.quick-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.qa-btn {
padding-block: 12px;
padding-inline: 16px;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 8px;
font-size: 0.85rem;
text-align: start;
transition: all 0.2s;
}
.qa-btn:hover {
border-color: var(--accent-blue);
background: rgba(59, 130, 246, 0.08);
}
/* Team list */
.team-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.team-member {
display: flex;
align-items: center;
gap: 12px;
}
.member-avatar {
inline-size: 40px;
block-size: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
font-weight: 600;
flex-shrink: 0;
}
.member-info {
flex: 1;
display: flex;
flex-direction: column;
}
.member-name {
font-size: 0.85rem;
font-weight: 500;
}
.member-role {
font-size: 0.75rem;
color: var(--text-muted);
}
.member-status {
inline-size: 10px;
block-size: 10px;
border-radius: 50%;
}
.member-status.online {
background: var(--accent-green);
}
.member-status.offline {
background: var(--text-muted);
}
/* ── Sidebar backdrop (mobile) ── */
.sidebar-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 99;
}
.sidebar-backdrop.active {
display: block;
}
/* ── Responsive — tablet ── */
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
}
[dir="rtl"] .sidebar {
transform: translateX(100%);
}
.sidebar.mobile-open {
transform: translateX(0);
}
.main-area {
margin-inline-start: 0;
}
.content {
padding-block: 16px;
padding-inline: 16px;
}
.stats-row {
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.card-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.topbar {
padding-inline: 12px;
}
.page-title {
font-size: 1rem;
}
}
/* ── Responsive — small phone ── */
@media (max-width: 480px) {
.stats-row {
grid-template-columns: 1fr;
gap: 8px;
}
.stat-card {
padding-block: 14px;
padding-inline: 14px;
gap: 12px;
}
.stat-icon {
inline-size: 40px;
block-size: 40px;
border-radius: 10px;
font-size: 1.2rem;
}
.stat-value {
font-size: 1.15rem;
}
.stat-label {
font-size: 0.75rem;
}
.content {
padding-block: 12px;
padding-inline: 12px;
}
.card {
padding-block: 16px;
padding-inline: 16px;
}
.quick-actions {
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.qa-btn {
padding-block: 10px;
padding-inline: 12px;
font-size: 0.8rem;
}
.topbar {
padding-inline: 10px;
gap: 8px;
}
.topbar-end {
gap: 4px;
}
.dir-toggle {
padding-block: 5px;
padding-inline: 10px;
font-size: 0.78rem;
}
.icon-btn {
padding: 6px;
font-size: 1rem;
}
.activity-item {
padding-block: 8px;
padding-inline: 10px;
}
.activity-text {
font-size: 0.8rem;
}
.activity-time {
font-size: 0.7rem;
}
.member-avatar {
inline-size: 34px;
block-size: 34px;
font-size: 0.75rem;
}
.member-name {
font-size: 0.8rem;
}
.card-title {
font-size: 0.9rem;
}
}(() => {
const html = document.documentElement;
const dirToggle = document.getElementById("dir-toggle");
const dirLabel = document.getElementById("dir-label");
const sidebarToggle = document.getElementById("sidebar-toggle");
const sidebar = document.getElementById("sidebar");
const mainArea = document.querySelector(".main-area");
const backdrop = document.getElementById("sidebar-backdrop");
const isMobile = () => window.innerWidth <= 768;
/* ── Direction toggle ── */
dirToggle.addEventListener("click", () => {
const isRtl = html.getAttribute("dir") === "rtl";
const newDir = isRtl ? "ltr" : "rtl";
html.setAttribute("dir", newDir);
html.setAttribute("lang", isRtl ? "en" : "ar");
dirLabel.textContent = newDir.toUpperCase();
});
/* ── Close sidebar on mobile ── */
function closeMobileSidebar() {
sidebar.classList.remove("mobile-open");
backdrop.classList.remove("active");
}
/* ── Sidebar toggle ── */
sidebarToggle.addEventListener("click", () => {
if (isMobile()) {
const opening = !sidebar.classList.contains("mobile-open");
sidebar.classList.toggle("mobile-open");
backdrop.classList.toggle("active", opening);
} else {
sidebar.classList.toggle("collapsed");
mainArea.classList.toggle("expanded");
}
});
/* ── Close sidebar when tapping backdrop ── */
backdrop.addEventListener("click", closeMobileSidebar);
/* ── Close sidebar on resize to desktop ── */
window.addEventListener("resize", () => {
if (!isMobile()) closeMobileSidebar();
});
})();<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RTL Layout</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="app-shell">
<!-- ── Sidebar backdrop (mobile) ── -->
<div class="sidebar-backdrop" id="sidebar-backdrop"></div>
<!-- ── Sidebar ── -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<span class="sidebar-logo">◆</span>
<span class="sidebar-brand">Workspace</span>
</div>
<nav class="sidebar-nav" aria-label="Main navigation">
<a href="#" class="nav-link active">
<span class="nav-icon">□</span>
<span class="nav-label">Dashboard</span>
</a>
<a href="#" class="nav-link">
<span class="nav-icon">☰</span>
<span class="nav-label">Projects</span>
</a>
<a href="#" class="nav-link">
<span class="nav-icon">✎</span>
<span class="nav-label">Documents</span>
</a>
<a href="#" class="nav-link">
<span class="nav-icon">☆</span>
<span class="nav-label">Favorites</span>
</a>
<a href="#" class="nav-link">
<span class="nav-icon">⚙</span>
<span class="nav-label">Settings</span>
</a>
</nav>
<div class="sidebar-footer">
<div class="user-badge">
<div class="user-avatar">JD</div>
<div class="user-info">
<span class="user-name">Jane Doe</span>
<span class="user-role">Admin</span>
</div>
</div>
</div>
</aside>
<!-- ── Main area ── -->
<div class="main-area">
<!-- ── Top nav ── -->
<header class="topbar">
<div class="topbar-start">
<button class="sidebar-toggle" id="sidebar-toggle" aria-label="Toggle sidebar">☰</button>
<h1 class="page-title">Dashboard</h1>
</div>
<div class="topbar-end">
<button class="dir-toggle" id="dir-toggle" aria-label="Toggle text direction">
<span class="dir-label" id="dir-label">LTR</span>
<span class="dir-arrow">⇄</span>
</button>
<button class="icon-btn" aria-label="Notifications">🔔</button>
<button class="icon-btn" aria-label="Search">🔍</button>
</div>
</header>
<!-- ── Content ── -->
<main class="content">
<!-- Stats row -->
<section class="stats-row">
<div class="stat-card">
<div class="stat-icon blue">📈</div>
<div class="stat-body">
<span class="stat-value">12,847</span>
<span class="stat-label">Total Users</span>
</div>
</div>
<div class="stat-card">
<div class="stat-icon green">💰</div>
<div class="stat-body">
<span class="stat-value">$48,290</span>
<span class="stat-label">Revenue</span>
</div>
</div>
<div class="stat-card">
<div class="stat-icon amber">📦</div>
<div class="stat-body">
<span class="stat-value">1,024</span>
<span class="stat-label">Orders</span>
</div>
</div>
<div class="stat-card">
<div class="stat-icon red">📊</div>
<div class="stat-body">
<span class="stat-value">3.2%</span>
<span class="stat-label">Conversion</span>
</div>
</div>
</section>
<!-- Content cards -->
<section class="card-grid">
<article class="card card-wide">
<div class="card-header">
<h2 class="card-title">Recent Activity</h2>
<button class="card-action">View all →</button>
</div>
<ul class="activity-list">
<li class="activity-item">
<span class="activity-dot green"></span>
<span class="activity-text">New user registration: <strong>Ahmed Hassan</strong></span>
<span class="activity-time">2 min ago</span>
</li>
<li class="activity-item">
<span class="activity-dot blue"></span>
<span class="activity-text">Invoice #4821 paid by <strong>Sara Ali</strong></span>
<span class="activity-time">15 min ago</span>
</li>
<li class="activity-item">
<span class="activity-dot amber"></span>
<span class="activity-text">Project "Alpha" deadline approaching</span>
<span class="activity-time">1 hr ago</span>
</li>
<li class="activity-item">
<span class="activity-dot red"></span>
<span class="activity-text">Server load exceeded 90% threshold</span>
<span class="activity-time">3 hrs ago</span>
</li>
</ul>
</article>
<article class="card">
<div class="card-header">
<h2 class="card-title">Quick Actions</h2>
</div>
<div class="quick-actions">
<button class="qa-btn">+ New Project</button>
<button class="qa-btn">📤 Send Report</button>
<button class="qa-btn">👥 Invite Member</button>
<button class="qa-btn">📅 Schedule</button>
</div>
</article>
<article class="card">
<div class="card-header">
<h2 class="card-title">Team Members</h2>
</div>
<div class="team-list">
<div class="team-member">
<div class="member-avatar" style="background:#3b82f6">AH</div>
<div class="member-info">
<span class="member-name">Ahmed Hassan</span>
<span class="member-role">Developer</span>
</div>
<span class="member-status online"></span>
</div>
<div class="team-member">
<div class="member-avatar" style="background:#8b5cf6">SA</div>
<div class="member-info">
<span class="member-name">Sara Ali</span>
<span class="member-role">Designer</span>
</div>
<span class="member-status online"></span>
</div>
<div class="team-member">
<div class="member-avatar" style="background:#f59e0b">MR</div>
<div class="member-info">
<span class="member-name">Mohamed Rashid</span>
<span class="member-role">Manager</span>
</div>
<span class="member-status offline"></span>
</div>
</div>
</article>
</section>
</main>
</div>
</div>
<script src="script.js"></script>
</body>
</html>A complete page layout built entirely with CSS logical properties, featuring a sidebar, top navigation, and content cards that seamlessly flip between LTR and RTL directions with a single toggle.