Refactor UI components and styles for improved consistency and aesthetics
This commit is contained in:
@@ -23,20 +23,18 @@ export function CreateButton({ onClick, disabled, icon, children }: CreateButton
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className="
|
className="
|
||||||
bg-pixel-purple-bright
|
bg-brand
|
||||||
hover:bg-pixel-purple-deep
|
hover:bg-brand-dark
|
||||||
text-white
|
text-white
|
||||||
border-[3px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel
|
shadow-card
|
||||||
hover:shadow-pixel-hover
|
hover:shadow-float
|
||||||
hover:-translate-y-0.5
|
hover:-translate-y-0.5
|
||||||
hover:-translate-x-0.5
|
|
||||||
active:translate-y-0.5
|
active:translate-y-0.5
|
||||||
active:translate-x-0.5
|
active:shadow-soft
|
||||||
active:shadow-pixel-active
|
|
||||||
transition-all
|
transition-all
|
||||||
duration-75
|
duration-150
|
||||||
font-sans
|
font-sans
|
||||||
font-semibold
|
font-semibold
|
||||||
px-6
|
px-6
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import type { DocumentType } from '@/api/document';
|
import type { DocumentType } from '@/api/document';
|
||||||
import { Card } from '@/components/ui/card';
|
import { Card } from '@/components/ui/card';
|
||||||
import { FileText, KanbanSquare, Trash2 } from 'lucide-react';
|
import { FileText, KanbanSquare, Trash2 } from 'lucide-react';
|
||||||
|
import PixelIcon from '@/components/PixelIcon/PixelIcon';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
interface DocumentCardProps {
|
interface DocumentCardProps {
|
||||||
@@ -24,15 +25,14 @@ export function DocumentCard({ doc, onDelete, isShared }: DocumentCardProps) {
|
|||||||
<Card className="
|
<Card className="
|
||||||
group
|
group
|
||||||
relative
|
relative
|
||||||
bg-pixel-white
|
bg-surface
|
||||||
border-[3px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-md
|
shadow-card
|
||||||
hover:shadow-pixel-lg
|
hover:shadow-float
|
||||||
hover:-translate-y-0.5
|
hover:-translate-y-0.5
|
||||||
hover:-translate-x-0.5
|
|
||||||
transition-all
|
transition-all
|
||||||
duration-100
|
duration-150
|
||||||
p-6
|
p-6
|
||||||
flex
|
flex
|
||||||
flex-col
|
flex-col
|
||||||
@@ -42,42 +42,32 @@ export function DocumentCard({ doc, onDelete, isShared }: DocumentCardProps) {
|
|||||||
<div className="flex items-start justify-between">
|
<div className="flex items-start justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="
|
<div className="
|
||||||
bg-pixel-cyan-bright
|
bg-brand-teal
|
||||||
p-2
|
p-2.5
|
||||||
border-[2px]
|
rounded-md
|
||||||
border-pixel-outline
|
shadow-soft
|
||||||
shadow-pixel-sm
|
|
||||||
">
|
">
|
||||||
<Icon className="w-6 h-6 text-white" />
|
<Icon className="w-5 h-5 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-pixel text-sm text-pixel-text-primary mb-1">
|
<h3 className="font-display text-base text-text-primary mb-1">
|
||||||
{doc.name}
|
{doc.name}
|
||||||
</h3>
|
</h3>
|
||||||
<span className="font-sans text-xs text-pixel-text-muted">
|
<span className="font-sans text-xs text-text-muted">
|
||||||
{typeLabel}
|
{typeLabel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isShared && (
|
{isShared && (
|
||||||
<span className="
|
<span className="shared-badge">
|
||||||
bg-pixel-pink-vibrant
|
<PixelIcon name="gem" size={12} color="hsl(var(--brand-teal))" />
|
||||||
text-white
|
|
||||||
font-sans
|
|
||||||
text-xs
|
|
||||||
font-semibold
|
|
||||||
px-2
|
|
||||||
py-1
|
|
||||||
border-[2px]
|
|
||||||
border-pixel-outline
|
|
||||||
">
|
|
||||||
Shared
|
Shared
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Metadata */}
|
{/* Metadata */}
|
||||||
<div className="font-sans text-xs text-pixel-text-muted">
|
<div className="font-sans text-xs text-text-muted">
|
||||||
Created {new Date(doc.created_at).toLocaleDateString()}
|
Created {new Date(doc.created_at).toLocaleDateString()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -87,17 +77,16 @@ export function DocumentCard({ doc, onDelete, isShared }: DocumentCardProps) {
|
|||||||
onClick={handleOpen}
|
onClick={handleOpen}
|
||||||
className="
|
className="
|
||||||
flex-1
|
flex-1
|
||||||
bg-pixel-cyan-bright
|
bg-brand
|
||||||
hover:bg-pixel-purple-bright
|
hover:bg-brand-dark
|
||||||
text-white
|
text-white
|
||||||
border-[2px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
hover:shadow-pixel-hover
|
hover:shadow-card
|
||||||
hover:-translate-y-0.5
|
hover:-translate-y-0.5
|
||||||
hover:-translate-x-0.5
|
|
||||||
transition-all
|
transition-all
|
||||||
duration-75
|
duration-150
|
||||||
font-sans
|
font-sans
|
||||||
font-semibold
|
font-semibold
|
||||||
"
|
"
|
||||||
@@ -109,15 +98,14 @@ export function DocumentCard({ doc, onDelete, isShared }: DocumentCardProps) {
|
|||||||
onClick={() => onDelete(doc.id)}
|
onClick={() => onDelete(doc.id)}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="
|
className="
|
||||||
border-[2px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
hover:shadow-pixel-hover
|
hover:shadow-card
|
||||||
hover:-translate-y-0.5
|
hover:-translate-y-0.5
|
||||||
hover:-translate-x-0.5
|
|
||||||
hover:bg-red-50
|
hover:bg-red-50
|
||||||
transition-all
|
transition-all
|
||||||
duration-75
|
duration-150
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4" />
|
<Trash2 className="w-4 h-4" />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useAuth } from '@/contexts/AuthContext';
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import PixelIcon from '@/components/PixelIcon/PixelIcon';
|
||||||
import { LogOut } from 'lucide-react';
|
import { LogOut } from 'lucide-react';
|
||||||
|
|
||||||
function Navbar() {
|
function Navbar() {
|
||||||
@@ -9,28 +10,33 @@ function Navbar() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="
|
<nav className="
|
||||||
bg-pixel-white
|
bg-surface
|
||||||
border-b-[3px]
|
border-b
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
sticky
|
sticky
|
||||||
top-0
|
top-0
|
||||||
z-50
|
z-50
|
||||||
|
backdrop-blur
|
||||||
">
|
">
|
||||||
<div className="max-w-7xl mx-auto px-8 py-4 flex items-center justify-between">
|
<div className="max-w-7xl mx-auto px-8 py-4 flex items-center justify-between">
|
||||||
{/* Brand */}
|
{/* Brand */}
|
||||||
<a
|
<a
|
||||||
href="/"
|
href="/"
|
||||||
className="
|
className="
|
||||||
font-pixel
|
font-display
|
||||||
text-xl
|
text-lg
|
||||||
text-pixel-purple-bright
|
text-text-primary
|
||||||
hover:text-pixel-cyan-bright
|
hover:text-brand
|
||||||
transition-colors
|
transition-colors
|
||||||
duration-200
|
duration-200
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
gap-2
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Realtime Collab
|
<PixelIcon name="gem" size={18} color="hsl(var(--brand-teal))" />
|
||||||
|
DocNest
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{/* User Section */}
|
{/* User Section */}
|
||||||
@@ -40,15 +46,17 @@ function Navbar() {
|
|||||||
src={user.avatar_url}
|
src={user.avatar_url}
|
||||||
alt={user.name}
|
alt={user.name}
|
||||||
className="
|
className="
|
||||||
w-10
|
w-9
|
||||||
h-10
|
h-9
|
||||||
border-[3px]
|
rounded-full
|
||||||
border-pixel-outline
|
border
|
||||||
shadow-pixel-sm
|
border-border
|
||||||
|
shadow-soft
|
||||||
|
object-cover
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<span className="font-sans font-medium text-pixel-text-primary hidden sm:inline">
|
<span className="font-sans font-medium text-text-primary hidden sm:inline">
|
||||||
{user.name}
|
{user.name}
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
@@ -56,14 +64,13 @@ function Navbar() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="
|
className="
|
||||||
border-[3px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
hover:shadow-pixel-hover
|
hover:shadow-card
|
||||||
hover:-translate-y-0.5
|
hover:-translate-y-0.5
|
||||||
hover:-translate-x-0.5
|
|
||||||
transition-all
|
transition-all
|
||||||
duration-75
|
duration-150
|
||||||
font-sans
|
font-sans
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -43,45 +43,37 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
}, [awareness]);
|
}, [awareness]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="
|
<div className="p-2">
|
||||||
bg-pixel-white
|
|
||||||
border-[3px]
|
|
||||||
border-pixel-outline
|
|
||||||
shadow-pixel-md
|
|
||||||
p-4
|
|
||||||
">
|
|
||||||
{/* Header with online count */}
|
{/* Header with online count */}
|
||||||
<div className="
|
<div className="
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
gap-2
|
gap-2
|
||||||
mb-4
|
mb-3
|
||||||
pb-3
|
pb-2
|
||||||
border-b-[2px]
|
border-b
|
||||||
border-pixel-outline
|
border-border
|
||||||
">
|
">
|
||||||
<div className="
|
<div className="
|
||||||
w-3
|
w-2.5
|
||||||
h-3
|
h-2.5
|
||||||
bg-pixel-green-lime
|
bg-brand-teal
|
||||||
animate-pulse
|
animate-pulse
|
||||||
border-[2px]
|
rounded-full
|
||||||
border-pixel-outline
|
|
||||||
" />
|
" />
|
||||||
<h4 className="font-pixel text-xs text-pixel-text-primary">
|
<h4 className="font-display text-xs text-text-secondary uppercase tracking-wide">
|
||||||
ONLINE
|
Online
|
||||||
</h4>
|
</h4>
|
||||||
<span className="
|
<span className="
|
||||||
ml-auto
|
ml-auto
|
||||||
font-sans
|
font-sans
|
||||||
text-sm
|
text-sm
|
||||||
font-bold
|
font-semibold
|
||||||
text-pixel-purple-bright
|
text-text-primary
|
||||||
bg-pixel-panel
|
bg-surface-muted
|
||||||
px-2
|
px-2
|
||||||
py-1
|
py-0.5
|
||||||
border-[2px]
|
rounded-full
|
||||||
border-pixel-outline
|
|
||||||
">
|
">
|
||||||
{users.length}
|
{users.length}
|
||||||
</span>
|
</span>
|
||||||
@@ -95,7 +87,7 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
py-4
|
py-4
|
||||||
font-sans
|
font-sans
|
||||||
text-xs
|
text-xs
|
||||||
text-pixel-text-muted
|
text-text-muted
|
||||||
">
|
">
|
||||||
No users online
|
No users online
|
||||||
</div>
|
</div>
|
||||||
@@ -108,16 +100,7 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
gap-3
|
gap-3
|
||||||
p-2
|
py-2
|
||||||
bg-pixel-panel
|
|
||||||
border-[2px]
|
|
||||||
border-pixel-outline
|
|
||||||
shadow-pixel-sm
|
|
||||||
hover:shadow-pixel-hover
|
|
||||||
hover:-translate-y-0.5
|
|
||||||
hover:-translate-x-0.5
|
|
||||||
transition-all
|
|
||||||
duration-75
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{/* Avatar with online indicator */}
|
{/* Avatar with online indicator */}
|
||||||
@@ -130,13 +113,14 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
className="
|
className="
|
||||||
w-10
|
w-10
|
||||||
h-10
|
h-10
|
||||||
border-[3px]
|
rounded-full
|
||||||
border-pixel-outline
|
border
|
||||||
shadow-pixel-sm
|
border-border
|
||||||
|
shadow-soft
|
||||||
object-cover
|
object-cover
|
||||||
"
|
"
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
// Fallback to colored square on image error
|
// Fallback to colored circle on image error
|
||||||
e.currentTarget.style.display = 'none';
|
e.currentTarget.style.display = 'none';
|
||||||
const fallback = e.currentTarget.nextElementSibling as HTMLElement;
|
const fallback = e.currentTarget.nextElementSibling as HTMLElement;
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
@@ -146,16 +130,15 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
/>
|
/>
|
||||||
{/* Fallback colored square (hidden if avatar loads) */}
|
{/* Fallback colored square (hidden if avatar loads) */}
|
||||||
<div
|
<div
|
||||||
className="w-10 h-10 border-[3px] border-pixel-outline shadow-pixel-sm items-center justify-center font-pixel text-xs text-white"
|
className="w-10 h-10 border border-border shadow-soft items-center justify-center font-display text-xs text-text-secondary rounded-full bg-surface-muted"
|
||||||
style={{ backgroundColor: user.color, display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
>
|
>
|
||||||
{user.name.charAt(0).toUpperCase()}
|
{user.name.charAt(0).toUpperCase()}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className="w-10 h-10 border-[3px] border-pixel-outline shadow-pixel-sm flex items-center justify-center font-pixel text-xs text-white"
|
className="w-10 h-10 border border-border shadow-soft flex items-center justify-center font-display text-xs text-text-secondary rounded-full bg-surface-muted"
|
||||||
style={{ backgroundColor: user.color }}
|
|
||||||
>
|
>
|
||||||
{user.name.charAt(0).toUpperCase()}
|
{user.name.charAt(0).toUpperCase()}
|
||||||
</div>
|
</div>
|
||||||
@@ -168,10 +151,11 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
-right-0.5
|
-right-0.5
|
||||||
w-3
|
w-3
|
||||||
h-3
|
h-3
|
||||||
bg-pixel-green-lime
|
bg-brand-teal
|
||||||
border-[2px]
|
border-2
|
||||||
border-pixel-white
|
border-white
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
|
rounded-full
|
||||||
" />
|
" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -180,25 +164,12 @@ const UserList = ({ awareness }: UserListProps) => {
|
|||||||
font-sans
|
font-sans
|
||||||
text-sm
|
text-sm
|
||||||
font-medium
|
font-medium
|
||||||
text-pixel-text-primary
|
text-text-primary
|
||||||
truncate
|
truncate
|
||||||
flex-1
|
flex-1
|
||||||
">
|
">
|
||||||
{user.name}
|
{user.name}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{/* User color indicator (small square) */}
|
|
||||||
<div
|
|
||||||
className="
|
|
||||||
flex-shrink-0
|
|
||||||
w-4
|
|
||||||
h-4
|
|
||||||
border-[2px]
|
|
||||||
border-pixel-outline
|
|
||||||
shadow-pixel-sm
|
|
||||||
"
|
|
||||||
style={{ backgroundColor: user.color }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(15, 23, 42, 0.45);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
animation: fadeIn 0.2s ease;
|
animation: fadeIn 0.2s ease;
|
||||||
|
backdrop-filter: blur(2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
@@ -18,11 +19,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
border-radius: 12px;
|
border-radius: var(--radius-lg);
|
||||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
border: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 600px;
|
max-width: 640px;
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -46,20 +48,54 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 20px 24px;
|
padding: 20px 24px;
|
||||||
border-bottom: 1px solid #e2e8f0;
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-header h2 {
|
.modal-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
color: #1a202c;
|
color: hsl(var(--text-primary));
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-banner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
margin: 16px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-banner.owner {
|
||||||
|
background: #ecfdf5;
|
||||||
|
color: #166534;
|
||||||
|
border: 1px solid #bbf7d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-banner.editor {
|
||||||
|
background: #fff7ed;
|
||||||
|
color: #9a3412;
|
||||||
|
border: 1px solid #fed7aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-banner.viewer {
|
||||||
|
background: #eff6ff;
|
||||||
|
color: #1d4ed8;
|
||||||
|
border: 1px solid #bfdbfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-icon {
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button {
|
.close-button {
|
||||||
background: none;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 28px;
|
font-size: 24px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -67,40 +103,43 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button:hover {
|
.close-button:hover {
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface-muted));
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
border-bottom: 1px solid #e2e8f0;
|
gap: 6px;
|
||||||
padding: 0 24px;
|
padding: 10px 16px;
|
||||||
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
padding: 12px 20px;
|
padding: 8px 14px;
|
||||||
background: none;
|
background: transparent;
|
||||||
border: none;
|
border: 1px solid transparent;
|
||||||
font-size: 14px;
|
border-radius: 999px;
|
||||||
font-weight: 500;
|
font-size: 13px;
|
||||||
color: #718096;
|
font-weight: 600;
|
||||||
|
color: hsl(var(--text-muted));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab:hover {
|
.tab:hover {
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab.active {
|
.tab.active {
|
||||||
color: #667eea;
|
color: white;
|
||||||
border-bottom-color: #667eea;
|
background: hsl(var(--primary));
|
||||||
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
@@ -110,72 +149,78 @@
|
|||||||
|
|
||||||
.message {
|
.message {
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-md);
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.error {
|
.message.error {
|
||||||
background: #fff5f5;
|
background: #fff1f2;
|
||||||
color: #c53030;
|
color: #b91c1c;
|
||||||
border: 1px solid #feb2b2;
|
border: 1px solid #fecdd3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.success {
|
.message.success {
|
||||||
background: #f0fff4;
|
background: #ecfdf5;
|
||||||
color: #22543d;
|
color: #166534;
|
||||||
border: 1px solid #9ae6b4;
|
border: 1px solid #bbf7d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-form {
|
.share-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-input {
|
.share-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 220px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-input:focus {
|
.share-input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #667eea;
|
border-color: hsl(var(--primary));
|
||||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
box-shadow: var(--focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-select {
|
.share-select {
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-select:focus {
|
.share-select:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #667eea;
|
border-color: hsl(var(--primary));
|
||||||
|
box-shadow: var(--focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-button {
|
.share-button {
|
||||||
padding: 10px 20px;
|
padding: 10px 18px;
|
||||||
background: #667eea;
|
background: hsl(var(--primary));
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-button:hover:not(:disabled) {
|
.share-button:hover:not(:disabled) {
|
||||||
background: #5568d3;
|
background: hsl(var(--primary) / 0.9);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-button:disabled {
|
.share-button:disabled {
|
||||||
@@ -186,15 +231,19 @@
|
|||||||
.shares-list h3 {
|
.shares-list h3 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
padding: 32px;
|
padding: 28px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-item {
|
.share-item {
|
||||||
@@ -202,9 +251,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 8px;
|
border-radius: var(--radius-md);
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-user {
|
.share-user {
|
||||||
@@ -214,10 +264,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.share-avatar {
|
.share-avatar {
|
||||||
width: 40px;
|
width: 36px;
|
||||||
height: 40px;
|
height: 36px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-info {
|
.share-info {
|
||||||
@@ -228,13 +279,13 @@
|
|||||||
|
|
||||||
.share-name {
|
.share-name {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-email {
|
.share-email {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-actions {
|
.share-actions {
|
||||||
@@ -244,28 +295,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.permission-badge {
|
.permission-badge {
|
||||||
padding: 4px 12px;
|
padding: 4px 10px;
|
||||||
background: #edf2f7;
|
background: hsl(var(--surface-muted));
|
||||||
color: #4a5568;
|
color: hsl(var(--text-secondary));
|
||||||
border-radius: 12px;
|
border-radius: 999px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-button {
|
.remove-button {
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
background: white;
|
background: white;
|
||||||
color: #e53e3e;
|
color: #b91c1c;
|
||||||
border: 1px solid #feb2b2;
|
border: 1px solid #fecdd3;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-button:hover:not(:disabled) {
|
.remove-button:hover:not(:disabled) {
|
||||||
background: #fff5f5;
|
background: #fff1f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-button:disabled {
|
.remove-button:disabled {
|
||||||
@@ -278,7 +329,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.link-creation p {
|
.link-creation p {
|
||||||
color: #4a5568;
|
color: hsl(var(--text-secondary));
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +338,7 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-display {
|
.link-display {
|
||||||
@@ -296,40 +348,42 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.link-display > p {
|
.link-display > p {
|
||||||
color: #4a5568;
|
color: hsl(var(--text-secondary));
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-box {
|
.link-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-input {
|
.link-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 240px;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface-muted));
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button {
|
.copy-button {
|
||||||
padding: 10px 20px;
|
padding: 10px 18px;
|
||||||
background: #48bb78;
|
background: hsl(var(--secondary));
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button:hover {
|
.copy-button:hover {
|
||||||
background: #38a169;
|
background: hsl(var(--secondary) / 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-meta {
|
.link-meta {
|
||||||
@@ -340,23 +394,23 @@
|
|||||||
|
|
||||||
.link-date {
|
.link-date {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
.revoke-button {
|
.revoke-button {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
background: white;
|
background: white;
|
||||||
color: #e53e3e;
|
color: #b91c1c;
|
||||||
border: 1px solid #feb2b2;
|
border: 1px solid #fecdd3;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revoke-button:hover:not(:disabled) {
|
.revoke-button:hover:not(:disabled) {
|
||||||
background: #fff5f5;
|
background: #fff1f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.revoke-button:disabled {
|
.revoke-button:disabled {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { shareApi } from '../../api/share';
|
import { shareApi } from '../../api/share';
|
||||||
import type { DocumentShareWithUser, ShareLink } from '../../types/share';
|
import type { DocumentShareWithUser, ShareLink } from '../../types/share';
|
||||||
|
import PixelIcon from '../PixelIcon/PixelIcon';
|
||||||
import './ShareModal.css';
|
import './ShareModal.css';
|
||||||
|
|
||||||
interface ShareModalProps {
|
interface ShareModalProps {
|
||||||
@@ -152,20 +153,8 @@ function ShareModal({ documentId, onClose, currentPermission, currentRole }: Sha
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{currentRole && (
|
{currentRole && (
|
||||||
<div
|
<div className={`role-banner ${currentRole}`}>
|
||||||
style={{
|
<span className="role-icon">
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '8px',
|
|
||||||
padding: '12px 16px',
|
|
||||||
backgroundColor: currentRole === 'owner' ? '#e8f5e9' : currentPermission === 'edit' ? '#fff3e0' : '#e3f2fd',
|
|
||||||
borderRadius: '8px',
|
|
||||||
margin: '16px 0',
|
|
||||||
fontSize: '14px',
|
|
||||||
fontWeight: '500',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span style={{ fontSize: '18px' }}>
|
|
||||||
{currentRole === 'owner' ? '👑' : currentPermission === 'edit' ? '✏️' : '👁️'}
|
{currentRole === 'owner' ? '👑' : currentPermission === 'edit' ? '✏️' : '👁️'}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
@@ -222,7 +211,10 @@ function ShareModal({ documentId, onClose, currentPermission, currentRole }: Sha
|
|||||||
<div className="shares-list">
|
<div className="shares-list">
|
||||||
<h3>People with access</h3>
|
<h3>People with access</h3>
|
||||||
{shares.length === 0 ? (
|
{shares.length === 0 ? (
|
||||||
<p className="empty-state">No users have been given access yet.</p>
|
<div className="empty-state">
|
||||||
|
<PixelIcon name="gem" size={18} color="hsl(var(--brand-teal))" />
|
||||||
|
<p>No users have been given access yet.</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
shares.map((share) => (
|
shares.map((share) => (
|
||||||
<div key={share.id} className="share-item">
|
<div key={share.id} className="share-item">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(15, 23, 42, 0.35);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
animation: fadeIn 0.2s ease;
|
animation: fadeIn 0.2s ease;
|
||||||
}
|
}
|
||||||
@@ -27,35 +27,42 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 400px;
|
width: 420px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);
|
border-left: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: -10px 0 30px rgba(15, 23, 42, 0.15);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
animation: slideIn 0.2s ease;
|
animation: slideIn 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.version-panel {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.version-panel-header {
|
.version-panel-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 20px 24px;
|
padding: 20px 24px;
|
||||||
border-bottom: 1px solid #e2e8f0;
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-panel-header h2 {
|
.version-panel-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #1a202c;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button {
|
.close-button {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 28px;
|
font-size: 24px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -63,35 +70,37 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-button:hover {
|
.close-button:hover {
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface-muted));
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-panel-actions {
|
.version-panel-actions {
|
||||||
padding: 16px 24px;
|
padding: 16px 24px;
|
||||||
border-bottom: 1px solid #e2e8f0;
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-version-btn {
|
.create-version-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
background: #667eea;
|
background: hsl(var(--primary));
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-version-btn:hover {
|
.create-version-btn:hover {
|
||||||
background: #5568d3;
|
background: hsl(var(--primary) / 0.9);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-panel-content {
|
.version-panel-content {
|
||||||
@@ -104,7 +113,14 @@
|
|||||||
.empty-state {
|
.empty-state {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state p {
|
.empty-state p {
|
||||||
@@ -114,20 +130,20 @@
|
|||||||
|
|
||||||
.empty-state small {
|
.empty-state small {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #a0aec0;
|
color: hsl(var(--text-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-md);
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.error {
|
.message.error {
|
||||||
background: #fff5f5;
|
background: #fff1f2;
|
||||||
color: #c53030;
|
color: #b91c1c;
|
||||||
border: 1px solid #feb2b2;
|
border: 1px solid #fecdd3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-list {
|
.version-list {
|
||||||
@@ -137,16 +153,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.version-item {
|
.version-item {
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface));
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 8px;
|
border-radius: var(--radius-md);
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-item:hover {
|
.version-item:hover {
|
||||||
border-color: #cbd5e0;
|
border-color: hsl(var(--primary) / 0.25);
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-header {
|
.version-header {
|
||||||
@@ -160,23 +177,23 @@
|
|||||||
.version-number {
|
.version-number {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.auto-badge {
|
.auto-badge {
|
||||||
background: #e8f4fd;
|
background: hsl(var(--surface-muted));
|
||||||
color: #3182ce;
|
color: hsl(var(--text-secondary));
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-radius: 10px;
|
border-radius: 999px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-label {
|
.version-label {
|
||||||
color: #667eea;
|
color: hsl(var(--primary));
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-meta {
|
.version-meta {
|
||||||
@@ -184,7 +201,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,21 +216,22 @@
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-time {
|
.version-time {
|
||||||
color: #a0aec0;
|
color: hsl(var(--text-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-preview {
|
.version-preview {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #4a5568;
|
color: hsl(var(--text-secondary));
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background: white;
|
background: hsl(var(--surface-muted));
|
||||||
border-radius: 4px;
|
border-radius: var(--radius-sm);
|
||||||
border: 1px solid #edf2f7;
|
border: 1px solid hsl(var(--border));
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@@ -221,18 +239,18 @@
|
|||||||
.restore-btn {
|
.restore-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
color: #667eea;
|
color: hsl(var(--primary));
|
||||||
border: 1px solid #667eea;
|
border: 1px solid hsl(var(--primary));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.restore-btn:hover:not(:disabled) {
|
.restore-btn:hover:not(:disabled) {
|
||||||
background: #667eea;
|
background: hsl(var(--primary));
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,21 +265,21 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
border-top: 1px solid #e2e8f0;
|
border-top: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination button {
|
.pagination button {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface-muted));
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination button:hover:not(:disabled) {
|
.pagination button:hover:not(:disabled) {
|
||||||
background: #edf2f7;
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination button:disabled {
|
.pagination button:disabled {
|
||||||
@@ -271,7 +289,7 @@
|
|||||||
|
|
||||||
.pagination span {
|
.pagination span {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #718096;
|
color: hsl(var(--text-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create Version Modal */
|
/* Create Version Modal */
|
||||||
@@ -281,7 +299,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(15, 23, 42, 0.5);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -289,39 +307,40 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.create-modal {
|
.create-modal {
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
border-radius: 12px;
|
border-radius: var(--radius-lg);
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 400px;
|
max-width: 420px;
|
||||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
border: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-modal h3 {
|
.create-modal h3 {
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
color: #1a202c;
|
color: hsl(var(--text-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-modal p {
|
.create-modal p {
|
||||||
margin: 0 0 20px 0;
|
margin: 0 0 20px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #718096;
|
color: hsl(var(--text-secondary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-modal label {
|
.create-modal label {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: #2d3748;
|
color: hsl(var(--text-primary));
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-modal input {
|
.create-modal input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -329,8 +348,8 @@
|
|||||||
|
|
||||||
.create-modal input:focus {
|
.create-modal input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #667eea;
|
border-color: hsl(var(--primary));
|
||||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
box-shadow: var(--focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons {
|
.modal-buttons {
|
||||||
@@ -341,31 +360,31 @@
|
|||||||
|
|
||||||
.modal-buttons button {
|
.modal-buttons button {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border-radius: 6px;
|
border-radius: var(--radius-sm);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons button:not(.primary) {
|
.modal-buttons button:not(.primary) {
|
||||||
background: #f7fafc;
|
background: hsl(var(--surface-muted));
|
||||||
color: #4a5568;
|
color: hsl(var(--text-secondary));
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons button:not(.primary):hover {
|
.modal-buttons button:not(.primary):hover {
|
||||||
background: #edf2f7;
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons button.primary {
|
.modal-buttons button.primary {
|
||||||
background: #667eea;
|
background: hsl(var(--primary));
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons button.primary:hover:not(:disabled) {
|
.modal-buttons button.primary:hover:not(:disabled) {
|
||||||
background: #5568d3;
|
background: hsl(var(--primary) / 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-buttons button:disabled {
|
.modal-buttons button:disabled {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { versionsApi, type DocumentVersion } from '../../api/document';
|
import { versionsApi, type DocumentVersion } from '../../api/document';
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
|
import PixelIcon from '../PixelIcon/PixelIcon';
|
||||||
import './VersionHistoryPanel.css';
|
import './VersionHistoryPanel.css';
|
||||||
|
|
||||||
interface VersionHistoryPanelProps {
|
interface VersionHistoryPanelProps {
|
||||||
@@ -180,6 +181,7 @@ function VersionHistoryPanel({ documentId, ydoc, canEdit, onClose }: VersionHist
|
|||||||
<div className="loading-state">Loading versions...</div>
|
<div className="loading-state">Loading versions...</div>
|
||||||
) : versions.length === 0 ? (
|
) : versions.length === 0 ? (
|
||||||
<div className="empty-state">
|
<div className="empty-state">
|
||||||
|
<PixelIcon name="gem" size={18} color="hsl(var(--brand-teal))" />
|
||||||
<p>No versions yet</p>
|
<p>No versions yet</p>
|
||||||
<small>Versions are created when you save manually or automatically over time</small>
|
<small>Versions are created when you save manually or automatically over time</small>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,29 +1,31 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Manrope:wght@500;600;700&display=swap');
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 232 217 243;
|
--background: 220 33% 98%;
|
||||||
--foreground: 43 27 56;
|
--foreground: 222 47% 11%;
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 43 27 56;
|
--card-foreground: 222 47% 11%;
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 43 27 56;
|
--popover-foreground: 222 47% 11%;
|
||||||
--primary: 277 42% 52%;
|
--primary: 214 89% 52%;
|
||||||
--primary-foreground: 0 0% 100%;
|
--primary-foreground: 0 0% 100%;
|
||||||
--secondary: 190 100% 50%;
|
--secondary: 173 80% 40%;
|
||||||
--secondary-foreground: 43 27 56;
|
--secondary-foreground: 0 0% 100%;
|
||||||
--muted: 276 100% 97%;
|
--muted: 220 16% 96%;
|
||||||
--muted-foreground: 240 13% 40%;
|
--muted-foreground: 215 16% 47%;
|
||||||
--accent: 325 100% 71%;
|
--accent: 188 92% 42%;
|
||||||
--accent-foreground: 0 0% 100%;
|
--accent-foreground: 0 0% 100%;
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 84.2% 60.2%;
|
||||||
--destructive-foreground: 0 0% 100%;
|
--destructive-foreground: 0 0% 100%;
|
||||||
--border: 43 27 56;
|
--border: 215 20% 90%;
|
||||||
--input: 43 27 56;
|
--input: 215 20% 90%;
|
||||||
--ring: 190 100% 50%;
|
--ring: 214 89% 52%;
|
||||||
--radius: 0rem;
|
--radius: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,41 +36,62 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* Vibrant Fantasy Color Palette */
|
/* Modern SaaS Design Tokens */
|
||||||
--pixel-purple-deep: #4A1B6F;
|
--surface: 0 0% 100%;
|
||||||
--pixel-purple-bright: #8B4FB9;
|
--surface-muted: 220 16% 96%;
|
||||||
--pixel-pink-vibrant: #FF6EC7;
|
--text-primary: 222 47% 11%;
|
||||||
--pixel-cyan-bright: #00D9FF;
|
--text-secondary: 215 25% 27%;
|
||||||
--pixel-orange-warm: #FF8E3C;
|
--text-muted: 215 16% 47%;
|
||||||
--pixel-yellow-gold: #FFD23F;
|
--brand: 214 89% 52%;
|
||||||
--pixel-green-lime: #8EF048;
|
--brand-dark: 221 83% 45%;
|
||||||
--pixel-green-forest: #3FA54D;
|
--brand-teal: 173 80% 40%;
|
||||||
|
--brand-teal-dark: 173 80% 32%;
|
||||||
|
|
||||||
/* UI Backgrounds & Neutrals */
|
--radius-sm: 8px;
|
||||||
--pixel-bg-dark: #2B1B38;
|
--radius-md: 12px;
|
||||||
--pixel-bg-medium: #4A3B5C;
|
--radius-lg: 16px;
|
||||||
--pixel-bg-light: #E8D9F3;
|
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.08);
|
||||||
--pixel-panel: #F5F0FF;
|
--shadow-md: 0 12px 30px rgba(15, 23, 42, 0.10);
|
||||||
|
--shadow-lg: 0 20px 50px rgba(15, 23, 42, 0.14);
|
||||||
|
--focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.25);
|
||||||
|
--gradient-hero: linear-gradient(120deg, #eef6ff 0%, #f5f7fb 55%, #ffffff 100%);
|
||||||
|
--gradient-accent: linear-gradient(120deg, #2563eb 0%, #14b8a6 100%);
|
||||||
|
|
||||||
|
/* Compatibility aliases (legacy pixel tokens mapped to modern palette) */
|
||||||
|
--pixel-purple-deep: #1E40AF;
|
||||||
|
--pixel-purple-bright: #2563EB;
|
||||||
|
--pixel-pink-vibrant: #38BDF8;
|
||||||
|
--pixel-cyan-bright: #14B8A6;
|
||||||
|
--pixel-orange-warm: #F59E0B;
|
||||||
|
--pixel-yellow-gold: #FBBF24;
|
||||||
|
--pixel-green-lime: #22C55E;
|
||||||
|
--pixel-green-forest: #16A34A;
|
||||||
|
|
||||||
|
--pixel-bg-dark: #0F172A;
|
||||||
|
--pixel-bg-medium: #1E293B;
|
||||||
|
--pixel-bg-light: #F5F7FB;
|
||||||
|
--pixel-panel: #FFFFFF;
|
||||||
--pixel-white: #FFFFFF;
|
--pixel-white: #FFFFFF;
|
||||||
|
|
||||||
/* Shadows & Outlines */
|
--pixel-shadow-dark: rgba(15, 23, 42, 0.2);
|
||||||
--pixel-shadow-dark: #1A0E28;
|
--pixel-outline: #E2E8F0;
|
||||||
--pixel-outline: #2B1B38;
|
|
||||||
|
|
||||||
/* Text Colors */
|
--pixel-text-primary: #0F172A;
|
||||||
--pixel-text-primary: #2B1B38;
|
--pixel-text-secondary: #334155;
|
||||||
--pixel-text-secondary: #4A3B5C;
|
--pixel-text-muted: #64748B;
|
||||||
--pixel-text-muted: #8B7B9C;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
background: var(--pixel-bg-light);
|
background: var(--gradient-hero);
|
||||||
background-image: url('/pixel-patterns.svg#pixel-checker-subtle');
|
color: hsl(var(--foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5 {
|
||||||
|
font-family: 'Manrope', 'Inter', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
@@ -77,54 +100,47 @@
|
|||||||
|
|
||||||
/* Pixel Art Utility Classes */
|
/* Pixel Art Utility Classes */
|
||||||
.pixel-border {
|
.pixel-border {
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
border-radius: var(--radius-md);
|
||||||
4px 4px 0 var(--pixel-shadow-dark),
|
box-shadow: var(--shadow-sm);
|
||||||
4px 4px 0 3px var(--pixel-outline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel-card {
|
.pixel-card {
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
border-radius: var(--radius-lg);
|
||||||
0 0 0 3px var(--pixel-outline),
|
box-shadow: var(--shadow-md);
|
||||||
6px 6px 0 var(--pixel-shadow-dark),
|
background: hsl(var(--surface));
|
||||||
6px 6px 0 3px var(--pixel-outline);
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||||
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel-card:hover {
|
.pixel-card:hover {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-2px);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-lg);
|
||||||
0 0 0 3px var(--pixel-outline),
|
|
||||||
8px 8px 0 var(--pixel-shadow-dark),
|
|
||||||
8px 8px 0 3px var(--pixel-outline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel-button {
|
.pixel-button {
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
border-radius: var(--radius-md);
|
||||||
4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.08s ease, box-shadow 0.08s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel-button:hover {
|
.pixel-button:hover {
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-md);
|
||||||
5px 5px 0 var(--pixel-shadow-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pixel-button:active {
|
.pixel-button:active {
|
||||||
transform: translate(2px, 2px);
|
transform: translateY(0);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-sm);
|
||||||
2px 2px 0 var(--pixel-shadow-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Focus states for accessibility */
|
/* Focus states for accessibility */
|
||||||
button:focus-visible,
|
button:focus-visible,
|
||||||
input:focus-visible {
|
input:focus-visible {
|
||||||
outline: 3px solid var(--pixel-yellow-gold);
|
outline: none;
|
||||||
outline-offset: 2px;
|
box-shadow: var(--focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reduced motion support */
|
/* Reduced motion support */
|
||||||
@@ -196,29 +212,29 @@
|
|||||||
|
|
||||||
.create-buttons button {
|
.create-buttons button {
|
||||||
padding: 0.75rem 1.5rem;
|
padding: 0.75rem 1.5rem;
|
||||||
background: var(--pixel-purple-bright);
|
background: hsl(var(--primary));
|
||||||
color: white;
|
color: hsl(var(--primary-foreground));
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-md);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-buttons button:hover {
|
.create-buttons button:hover {
|
||||||
background: var(--pixel-purple-deep);
|
background: hsl(var(--primary) / 0.9);
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 5px 5px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-buttons button:active {
|
.create-buttons button:active {
|
||||||
transform: translate(2px, 2px);
|
transform: translateY(0);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-buttons button:disabled {
|
.create-buttons button:disabled {
|
||||||
@@ -234,21 +250,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.document-card {
|
.document-card {
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
border-radius: 0;
|
border-radius: var(--radius-lg);
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
box-shadow: var(--shadow-md);
|
||||||
6px 6px 0 var(--pixel-shadow-dark),
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||||
6px 6px 0 3px var(--pixel-outline);
|
|
||||||
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-card:hover {
|
.document-card:hover {
|
||||||
transform: translate(-2px, -2px);
|
transform: translateY(-2px);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-lg);
|
||||||
8px 8px 0 var(--pixel-shadow-dark),
|
|
||||||
8px 8px 0 3px var(--pixel-outline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-info h3 {
|
.doc-info h3 {
|
||||||
@@ -256,13 +268,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.doc-type {
|
.doc-type {
|
||||||
color: var(--pixel-text-secondary);
|
color: hsl(var(--text-secondary));
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-date {
|
.doc-date {
|
||||||
color: var(--pixel-text-muted);
|
color: hsl(var(--text-muted));
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,37 +286,37 @@
|
|||||||
|
|
||||||
.doc-actions button {
|
.doc-actions button {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 44px;
|
min-width: 44px;
|
||||||
min-height: 44px;
|
min-height: 44px;
|
||||||
box-shadow: 3px 3px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-actions button:hover {
|
.doc-actions button:hover {
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-actions button:active {
|
.doc-actions button:active {
|
||||||
transform: translate(1px, 1px);
|
transform: translateY(0);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-actions button:first-child {
|
.doc-actions button:first-child {
|
||||||
background: var(--pixel-cyan-bright);
|
background: hsl(var(--secondary));
|
||||||
color: white;
|
color: hsl(var(--secondary-foreground));
|
||||||
border-color: var(--pixel-outline);
|
border-color: hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.doc-actions button:first-child:hover {
|
.doc-actions button:first-child:hover {
|
||||||
background: var(--pixel-purple-bright);
|
background: hsl(var(--primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Editor Page */
|
/* Editor Page */
|
||||||
@@ -312,6 +324,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
background: hsl(var(--background));
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
@@ -319,38 +332,104 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
border-bottom: 3px solid var(--pixel-outline);
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header button {
|
.page-header button {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
background: var(--pixel-panel);
|
background: hsl(var(--surface));
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 44px;
|
min-width: 44px;
|
||||||
min-height: 44px;
|
min-height: 44px;
|
||||||
box-shadow: 3px 3px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header button:hover {
|
.page-header button:hover {
|
||||||
background: var(--pixel-bg-light);
|
background: hsl(var(--surface-muted));
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header button:active {
|
.page-header button:active {
|
||||||
transform: translate(1px, 1px);
|
transform: translateY(0);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sync-status {
|
.sync-status {
|
||||||
color: var(--pixel-text-secondary);
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: hsl(var(--text-secondary));
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sync-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: hsl(var(--surface-muted));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.sync-dot.synced {
|
||||||
|
background: hsl(var(--secondary));
|
||||||
|
border-color: hsl(var(--secondary));
|
||||||
|
box-shadow: 0 0 0 2px rgba(20, 184, 166, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sync-dot.syncing {
|
||||||
|
background: hsl(var(--primary));
|
||||||
|
border-color: hsl(var(--primary));
|
||||||
|
animation: pulse-dot 1.2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-dot {
|
||||||
|
0%, 100% { transform: scale(1); opacity: 0.7; }
|
||||||
|
50% { transform: scale(1.2); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-only-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: hsl(var(--surface));
|
||||||
|
color: hsl(var(--text-secondary));
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-only-icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
color: hsl(var(--text-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.shared-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: hsl(var(--text-secondary));
|
||||||
|
background: hsl(var(--surface-muted));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 2px 2px 0 rgba(15, 23, 42, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
.page-content {
|
.page-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column; /* Mobile: stack vertically */
|
flex-direction: column; /* Mobile: stack vertically */
|
||||||
@@ -384,9 +463,8 @@
|
|||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 100%; /* Mobile: full width */
|
width: 100%; /* Mobile: full width */
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
background-image: url('/pixel-patterns.svg#pixel-scanlines');
|
border-top: 1px solid hsl(var(--border)); /* Mobile: top border */
|
||||||
border-top: 3px solid var(--pixel-outline); /* Mobile: top border */
|
|
||||||
border-left: none;
|
border-left: none;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
max-height: 200px; /* Mobile: limit height */
|
max-height: 200px; /* Mobile: limit height */
|
||||||
@@ -398,18 +476,16 @@
|
|||||||
width: 250px; /* Desktop: fixed width */
|
width: 250px; /* Desktop: fixed width */
|
||||||
max-height: none;
|
max-height: none;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
border-left: 3px solid var(--pixel-outline);
|
border-left: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Editor */
|
/* Editor */
|
||||||
.editor-container {
|
.editor-container {
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-lg);
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
box-shadow: var(--shadow-md);
|
||||||
6px 6px 0 var(--pixel-shadow-dark),
|
|
||||||
6px 6px 0 3px var(--pixel-outline);
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,41 +493,39 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
background: var(--pixel-panel);
|
background: hsl(var(--surface-muted));
|
||||||
background-image: url('/pixel-patterns.svg#pixel-panel-texture');
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
border-bottom: 3px solid var(--pixel-outline);
|
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar button {
|
.toolbar button {
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 44px;
|
min-width: 44px;
|
||||||
min-height: 44px;
|
min-height: 44px;
|
||||||
box-shadow: 3px 3px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar button:hover {
|
.toolbar button:hover {
|
||||||
background: var(--pixel-bg-light);
|
background: hsl(var(--surface-muted));
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar button:active {
|
.toolbar button:active {
|
||||||
transform: translate(1px, 1px);
|
transform: translateY(0);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar button.active {
|
.toolbar button.active {
|
||||||
background: var(--pixel-cyan-bright);
|
background: hsl(var(--secondary));
|
||||||
color: white;
|
color: hsl(var(--secondary-foreground));
|
||||||
border-color: var(--pixel-outline);
|
border-color: hsl(var(--border));
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transform: translate(1px, 1px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-content {
|
.editor-content {
|
||||||
@@ -496,12 +570,13 @@
|
|||||||
/* Collaborative Cursors */
|
/* Collaborative Cursors */
|
||||||
.collaboration-cursor__caret {
|
.collaboration-cursor__caret {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-left: 2px solid;
|
border-left: 3px solid;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
margin-right: -1px;
|
margin-right: -1px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
|
box-shadow: 1px 0 0 currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collaboration-cursor__label {
|
.collaboration-cursor__label {
|
||||||
@@ -515,7 +590,8 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
border-radius: 0;
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3);
|
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
@@ -537,14 +613,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-column {
|
.kanban-column {
|
||||||
background: var(--pixel-panel);
|
background: hsl(var(--surface));
|
||||||
background-image: url('/pixel-patterns.svg#pixel-dither-diagonal');
|
border-radius: var(--radius-lg);
|
||||||
border-radius: 0;
|
border: 1px solid hsl(var(--border));
|
||||||
border: 3px solid var(--pixel-outline);
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
width: 100%; /* Mobile: full width */
|
width: 100%; /* Mobile: full width */
|
||||||
min-width: unset;
|
min-width: unset;
|
||||||
max-width: unset;
|
max-width: unset;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
@@ -574,22 +650,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-card {
|
.kanban-card {
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0;
|
border-radius: var(--radius-md);
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
box-shadow: var(--shadow-sm);
|
||||||
4px 4px 0 var(--pixel-shadow-dark),
|
|
||||||
4px 4px 0 3px var(--pixel-outline);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-card:hover {
|
.kanban-card:hover {
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-md);
|
||||||
5px 5px 0 var(--pixel-shadow-dark),
|
|
||||||
5px 5px 0 3px var(--pixel-outline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.kanban-card h4 {
|
.kanban-card h4 {
|
||||||
@@ -597,38 +669,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.kanban-card p {
|
.kanban-card p {
|
||||||
color: var(--pixel-text-secondary);
|
color: hsl(var(--text-secondary));
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-task-btn {
|
.add-task-btn {
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
border: 3px dashed var(--pixel-outline);
|
border: 1px dashed hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-md);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--pixel-text-secondary);
|
color: hsl(var(--text-secondary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-task-btn:hover {
|
.add-task-btn:hover {
|
||||||
border-color: var(--pixel-purple-bright);
|
border-color: hsl(var(--primary));
|
||||||
color: var(--pixel-text-primary);
|
color: hsl(var(--text-primary));
|
||||||
background: var(--pixel-bg-light);
|
background: hsl(var(--surface-muted));
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-task-form input {
|
.add-task-form input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
border: 2px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-sm);
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-task-form input:focus {
|
.add-task-form input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--pixel-cyan-bright);
|
border-color: hsl(var(--primary));
|
||||||
box-shadow: 0 0 0 2px var(--pixel-cyan-bright);
|
box-shadow: var(--focus-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions {
|
.form-actions {
|
||||||
@@ -638,28 +710,28 @@
|
|||||||
|
|
||||||
.form-actions button {
|
.form-actions button {
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 0;
|
border-radius: var(--radius-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
box-shadow: 3px 3px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
transition: transform 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions button:hover {
|
.form-actions button:hover {
|
||||||
transform: translate(-1px, -1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions button:active {
|
.form-actions button:active {
|
||||||
transform: translate(1px, 1px);
|
transform: translateY(0);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions button:first-child {
|
.form-actions button:first-child {
|
||||||
background: var(--pixel-green-lime);
|
background: hsl(var(--secondary));
|
||||||
color: var(--pixel-text-primary);
|
color: hsl(var(--secondary-foreground));
|
||||||
border-color: var(--pixel-outline);
|
border-color: hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* User List */
|
/* User List */
|
||||||
@@ -682,8 +754,8 @@
|
|||||||
.user-color {
|
.user-color {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
border-radius: 0;
|
border-radius: 999px;
|
||||||
border: 1px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-name {
|
.user-name {
|
||||||
@@ -696,5 +768,5 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: var(--pixel-text-secondary);
|
color: hsl(var(--text-secondary));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import UserList from "../components/Presence/UserList.tsx";
|
|||||||
import ShareModal from "../components/Share/ShareModal.tsx";
|
import ShareModal from "../components/Share/ShareModal.tsx";
|
||||||
import VersionHistoryPanel from "../components/VersionHistory/VersionHistoryPanel.tsx";
|
import VersionHistoryPanel from "../components/VersionHistory/VersionHistoryPanel.tsx";
|
||||||
import { useYjsDocument } from "../hooks/useYjsDocument.ts";
|
import { useYjsDocument } from "../hooks/useYjsDocument.ts";
|
||||||
|
import { Eye } from "lucide-react";
|
||||||
|
|
||||||
const EditorPage = () => {
|
const EditorPage = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
@@ -27,14 +28,11 @@ const EditorPage = () => {
|
|||||||
<button onClick={() => navigate("/")}>← Back to Home</button>
|
<button onClick={() => navigate("/")}>← Back to Home</button>
|
||||||
<div className="header-actions">
|
<div className="header-actions">
|
||||||
{permission !== "edit" && permission !== null && (
|
{permission !== "edit" && permission !== null && (
|
||||||
<div className="view-only-badge" style={{ display: 'flex', alignItems: 'center', gap: '4px', padding: '4px 12px', backgroundColor: '#f0f0f0', borderRadius: '4px', fontSize: '14px' }}>
|
<div className="view-only-badge">
|
||||||
<span>👁️</span>
|
<Eye className="view-only-icon" />
|
||||||
<span>View only</span>
|
<span>View only</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="sync-status">
|
|
||||||
{synced ? "✓ Synced" : "⟳ Syncing..."}
|
|
||||||
</div>
|
|
||||||
{!shareToken && (
|
{!shareToken && (
|
||||||
<button className="share-btn" onClick={() => setShowShareModal(true)}>
|
<button className="share-btn" onClick={() => setShowShareModal(true)}>
|
||||||
Share
|
Share
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { documentsApi } from '@/api/document';
|
|||||||
import Navbar from '@/components/Navbar';
|
import Navbar from '@/components/Navbar';
|
||||||
import { DocumentCard } from '@/components/Home/DocumentCard';
|
import { DocumentCard } from '@/components/Home/DocumentCard';
|
||||||
import { CreateButton } from '@/components/Home/CreateButton';
|
import { CreateButton } from '@/components/Home/CreateButton';
|
||||||
import FloatingGem from '@/components/PixelSprites/FloatingGem';
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
|
import PixelIcon from '@/components/PixelIcon/PixelIcon';
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@@ -64,8 +64,8 @@ const Home = () => {
|
|||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center bg-pixel-bg-light">
|
<div className="min-h-screen flex items-center justify-center bg-background">
|
||||||
<div className="font-pixel text-pixel-purple-bright animate-pixel-bounce">
|
<div className="text-brand text-base font-medium">
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,15 +75,11 @@ const Home = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div className="max-w-7xl mx-auto px-8 py-12 relative min-h-screen bg-pixel-bg-light">
|
<div className="max-w-7xl mx-auto px-8 py-12 relative min-h-screen bg-background">
|
||||||
{/* Decorative floating gems */}
|
|
||||||
<FloatingGem position={{ top: '20px', right: '40px' }} delay={0} size={40} />
|
|
||||||
<FloatingGem position={{ top: '60px', left: '60px' }} delay={1.5} size={32} />
|
|
||||||
<FloatingGem position={{ bottom: '100px', right: '100px' }} delay={3} size={36} />
|
|
||||||
|
|
||||||
{/* Page Header */}
|
{/* Page Header */}
|
||||||
<div className="mb-12">
|
<div className="mb-12">
|
||||||
<h1 className="font-pixel text-4xl text-pixel-purple-bright mb-6 tracking-wide">
|
<h1 className="font-display text-3xl text-text-primary mb-4">
|
||||||
My Workspace
|
My Workspace
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -109,10 +105,10 @@ const Home = () => {
|
|||||||
{/* Tabbed Interface */}
|
{/* Tabbed Interface */}
|
||||||
<Tabs defaultValue="owned" className="w-full">
|
<Tabs defaultValue="owned" className="w-full">
|
||||||
<TabsList className="
|
<TabsList className="
|
||||||
bg-pixel-panel
|
bg-surface-muted
|
||||||
border-[3px]
|
border
|
||||||
border-pixel-outline
|
border-border
|
||||||
shadow-pixel-sm
|
shadow-soft
|
||||||
p-1
|
p-1
|
||||||
mb-8
|
mb-8
|
||||||
">
|
">
|
||||||
@@ -121,9 +117,9 @@ const Home = () => {
|
|||||||
className="
|
className="
|
||||||
font-sans
|
font-sans
|
||||||
font-semibold
|
font-semibold
|
||||||
data-[state=active]:bg-pixel-cyan-bright
|
data-[state=active]:bg-surface
|
||||||
data-[state=active]:text-white
|
data-[state=active]:text-text-primary
|
||||||
data-[state=active]:shadow-pixel-sm
|
data-[state=active]:shadow-soft
|
||||||
transition-all
|
transition-all
|
||||||
duration-100
|
duration-100
|
||||||
"
|
"
|
||||||
@@ -135,9 +131,9 @@ const Home = () => {
|
|||||||
className="
|
className="
|
||||||
font-sans
|
font-sans
|
||||||
font-semibold
|
font-semibold
|
||||||
data-[state=active]:bg-pixel-cyan-bright
|
data-[state=active]:bg-surface
|
||||||
data-[state=active]:text-white
|
data-[state=active]:text-text-primary
|
||||||
data-[state=active]:shadow-pixel-sm
|
data-[state=active]:shadow-soft
|
||||||
transition-all
|
transition-all
|
||||||
duration-100
|
duration-100
|
||||||
"
|
"
|
||||||
@@ -150,9 +146,10 @@ const Home = () => {
|
|||||||
<TabsContent value="owned">
|
<TabsContent value="owned">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{ownedDocuments.length === 0 ? (
|
{ownedDocuments.length === 0 ? (
|
||||||
<p className="col-span-full text-center text-pixel-text-muted font-sans py-12">
|
<div className="col-span-full flex flex-col items-center gap-3 text-text-muted font-sans py-12">
|
||||||
No documents yet. Create one to get started!
|
<PixelIcon name="gem" size={20} color="hsl(var(--brand-teal))" />
|
||||||
</p>
|
<p>No documents yet. Create one to get started!</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
ownedDocuments.map((doc) => (
|
ownedDocuments.map((doc) => (
|
||||||
<DocumentCard
|
<DocumentCard
|
||||||
@@ -170,9 +167,10 @@ const Home = () => {
|
|||||||
<TabsContent value="shared">
|
<TabsContent value="shared">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{sharedDocuments.length === 0 ? (
|
{sharedDocuments.length === 0 ? (
|
||||||
<p className="col-span-full text-center text-pixel-text-muted font-sans py-12">
|
<div className="col-span-full flex flex-col items-center gap-3 text-text-muted font-sans py-12">
|
||||||
No shared documents yet.
|
<PixelIcon name="gem" size={20} color="hsl(var(--brand-teal))" />
|
||||||
</p>
|
<p>No shared documents yet.</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
sharedDocuments.map((doc) => (
|
sharedDocuments.map((doc) => (
|
||||||
<DocumentCard
|
<DocumentCard
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ const KanbanPage = () => {
|
|||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<button onClick={() => navigate("/")}>← Back to Home</button>
|
<button onClick={() => navigate("/")}>← Back to Home</button>
|
||||||
<div className="header-actions">
|
<div className="header-actions">
|
||||||
<div className="sync-status">
|
|
||||||
{synced ? "✓ Synced" : "⟳ Syncing..."}
|
|
||||||
</div>
|
|
||||||
{!shareToken && (
|
{!shareToken && (
|
||||||
<button className="share-btn" onClick={() => setShowShareModal(true)}>
|
<button className="share-btn" onClick={() => setShowShareModal(true)}>
|
||||||
Share
|
Share
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
.landing-page {
|
.landing-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
overflow-x: hidden;
|
color: hsl(var(--text-primary));
|
||||||
|
background: hsl(var(--background));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================
|
/* ========================================
|
||||||
@@ -10,248 +11,313 @@
|
|||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
.landing-hero {
|
.landing-hero {
|
||||||
min-height: 100vh;
|
min-height: 90vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 2rem;
|
padding: 6rem 2rem 5rem;
|
||||||
|
background: var(--gradient-hero);
|
||||||
/* Animated gradient background */
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
var(--pixel-purple-deep) 0%,
|
|
||||||
var(--pixel-purple-bright) 40%,
|
|
||||||
var(--pixel-pink-vibrant) 100%
|
|
||||||
);
|
|
||||||
background-size: 200% 200%;
|
|
||||||
animation: gradient-shift 12s ease infinite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes gradient-shift {
|
.hero-gem svg {
|
||||||
0%, 100% {
|
opacity: 0.18;
|
||||||
background-position: 0% 50%;
|
filter: drop-shadow(0 10px 20px rgba(15, 23, 42, 0.2));
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-position: 100% 50%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hero-grid {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: grid;
|
||||||
|
gap: 3rem;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-content {
|
.hero-content {
|
||||||
text-align: center;
|
text-align: left;
|
||||||
z-index: 10;
|
|
||||||
max-width: 800px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-logo {
|
.hero-logo {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
gap: 12px;
|
||||||
gap: 16px;
|
padding: 0.4rem 0.85rem;
|
||||||
margin-bottom: 2rem;
|
border-radius: 999px;
|
||||||
|
background: hsl(var(--surface));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-brand {
|
.hero-brand {
|
||||||
font-size: 3rem;
|
font-size: 0.95rem;
|
||||||
font-weight: 800;
|
font-weight: 700;
|
||||||
color: var(--pixel-white);
|
letter-spacing: 0.04em;
|
||||||
text-shadow:
|
text-transform: uppercase;
|
||||||
4px 4px 0 var(--pixel-shadow-dark),
|
color: hsl(var(--text-secondary));
|
||||||
-1px -1px 0 var(--pixel-shadow-dark),
|
|
||||||
1px -1px 0 var(--pixel-shadow-dark),
|
|
||||||
-1px 1px 0 var(--pixel-shadow-dark);
|
|
||||||
margin: 0;
|
|
||||||
letter-spacing: -1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-headline {
|
.hero-headline {
|
||||||
font-size: 2.5rem;
|
font-size: 2.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--pixel-white);
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0 0 1.25rem 0;
|
||||||
text-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
line-height: 1.1;
|
||||||
line-height: 1.2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-tagline {
|
.hero-tagline {
|
||||||
font-size: 1.25rem;
|
font-size: 1.1rem;
|
||||||
color: var(--pixel-bg-light);
|
color: hsl(var(--text-secondary));
|
||||||
margin: 0 0 3rem 0;
|
margin: 0 0 2rem 0;
|
||||||
line-height: 1.6;
|
line-height: 1.7;
|
||||||
opacity: 0.95;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-login-buttons {
|
.hero-login-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-scroll-hint {
|
.hero-note {
|
||||||
position: absolute;
|
font-size: 0.9rem;
|
||||||
bottom: 2rem;
|
color: hsl(var(--text-muted));
|
||||||
left: 50%;
|
margin: 0;
|
||||||
transform: translateX(-50%);
|
|
||||||
color: var(--pixel-white);
|
|
||||||
opacity: 0.6;
|
|
||||||
animation: bounce-hint 2s ease-in-out infinite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes bounce-hint {
|
.provider-buttons {
|
||||||
0%, 100% {
|
display: flex;
|
||||||
transform: translateX(-50%) translateY(0);
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
50% {
|
|
||||||
transform: translateX(-50%) translateY(10px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================
|
|
||||||
Login Buttons
|
|
||||||
======================================== */
|
|
||||||
|
|
||||||
.landing-login-button {
|
.landing-login-button {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
padding: 1rem 2rem;
|
padding: 0.9rem 1.4rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background: hsl(var(--surface));
|
||||||
|
color: hsl(var(--text-primary));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.05s ease, box-shadow 0.05s ease;
|
box-shadow: var(--shadow-sm);
|
||||||
min-width: 260px;
|
transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-login-button.google {
|
.landing-login-button:hover {
|
||||||
background: var(--pixel-white);
|
transform: translateY(-1px);
|
||||||
color: var(--pixel-text-primary);
|
box-shadow: var(--shadow-md);
|
||||||
box-shadow: 4px 4px 0 var(--pixel-shadow-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-login-button.google:hover {
|
.landing-login-button.primary {
|
||||||
transform: translate(-2px, -2px);
|
background: var(--gradient-accent);
|
||||||
box-shadow: 6px 6px 0 var(--pixel-shadow-dark);
|
color: white;
|
||||||
background: var(--pixel-panel);
|
border: none;
|
||||||
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-login-button.google:active {
|
.landing-login-button.primary:hover {
|
||||||
transform: translate(2px, 2px);
|
filter: brightness(0.98);
|
||||||
box-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-login-button.github {
|
.landing-login-button.provider {
|
||||||
background: var(--pixel-bg-dark);
|
background: hsl(var(--surface));
|
||||||
color: var(--pixel-white);
|
|
||||||
box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-login-button.github:hover {
|
|
||||||
transform: translate(-2px, -2px);
|
|
||||||
box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
background: var(--pixel-bg-medium);
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-login-button.github:active {
|
|
||||||
transform: translate(2px, 2px);
|
|
||||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-login-button.large {
|
.landing-login-button.large {
|
||||||
padding: 1.25rem 2.5rem;
|
padding: 1rem 2rem;
|
||||||
font-size: 1.125rem;
|
font-size: 1.05rem;
|
||||||
min-width: 300px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.oauth-icon {
|
.oauth-icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hero-mock {
|
||||||
|
background: hsl(var(--surface));
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-topbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid hsl(var(--border));
|
||||||
|
background: hsl(var(--surface-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-body {
|
||||||
|
padding: 20px 22px 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: hsl(var(--text-muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-tab {
|
||||||
|
padding-bottom: 6px;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-tab.active {
|
||||||
|
color: hsl(var(--text-primary));
|
||||||
|
border-bottom-color: hsl(var(--primary));
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-card {
|
||||||
|
background: hsl(var(--surface-muted));
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 14px;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-line {
|
||||||
|
height: 8px;
|
||||||
|
background: hsl(var(--border));
|
||||||
|
border-radius: 999px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-line.wide {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-line.short {
|
||||||
|
width: 55%;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-rows {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 24px 1fr 80px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-pill {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: hsl(var(--secondary));
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================================
|
/* ========================================
|
||||||
Features Section
|
Features Section
|
||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
.landing-features {
|
.landing-features {
|
||||||
padding: 6rem 2rem;
|
padding: 5rem 2rem;
|
||||||
background: var(--pixel-bg-light);
|
background: hsl(var(--background));
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
|
.section-divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 0 2rem;
|
||||||
|
background: hsl(var(--background));
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider-line {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 2.5rem;
|
font-size: 2.25rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--pixel-text-primary);
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 4rem 0;
|
margin: 0 0 3rem 0;
|
||||||
text-shadow: 2px 2px 0 var(--pixel-white);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.features-grid {
|
.features-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 2rem;
|
gap: 1.75rem;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card {
|
.feature-card {
|
||||||
background: var(--pixel-white);
|
background: hsl(var(--surface));
|
||||||
padding: 2.5rem 2rem;
|
padding: 2rem;
|
||||||
border: 3px solid var(--pixel-outline);
|
border: 1px solid hsl(var(--border));
|
||||||
box-shadow:
|
border-radius: var(--radius-lg);
|
||||||
0 0 0 3px var(--pixel-outline),
|
box-shadow: var(--shadow-sm);
|
||||||
6px 6px 0 var(--pixel-shadow-dark),
|
text-align: left;
|
||||||
6px 6px 0 3px var(--pixel-outline);
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||||
text-align: center;
|
|
||||||
transition: transform 0.1s ease, box-shadow 0.1s ease;
|
|
||||||
opacity: 0;
|
|
||||||
animation: fade-in-up 0.6s ease forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card:nth-child(1) { animation-delay: 0.1s; }
|
|
||||||
.feature-card:nth-child(2) { animation-delay: 0.2s; }
|
|
||||||
.feature-card:nth-child(3) { animation-delay: 0.3s; }
|
|
||||||
.feature-card:nth-child(4) { animation-delay: 0.4s; }
|
|
||||||
|
|
||||||
@keyframes fade-in-up {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(20px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card:hover {
|
.feature-card:hover {
|
||||||
transform: translate(-3px, -3px);
|
transform: translateY(-2px);
|
||||||
box-shadow:
|
box-shadow: var(--shadow-md);
|
||||||
0 0 0 3px var(--pixel-outline),
|
|
||||||
9px 9px 0 var(--pixel-shadow-dark),
|
|
||||||
9px 9px 0 3px var(--pixel-outline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-icon {
|
.feature-icon {
|
||||||
margin-bottom: 1.5rem;
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: hsl(var(--surface-muted));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-title {
|
.feature-title {
|
||||||
font-size: 1.25rem;
|
font-size: 1.15rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--pixel-text-primary);
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 0.75rem 0;
|
margin: 0 0 0.6rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-description {
|
.feature-description {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--pixel-text-secondary);
|
color: hsl(var(--text-secondary));
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1.5;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================
|
/* ========================================
|
||||||
@@ -259,44 +325,39 @@
|
|||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
.landing-footer {
|
.landing-footer {
|
||||||
padding: 6rem 2rem;
|
padding: 4.5rem 2rem;
|
||||||
background: var(--pixel-bg-dark);
|
background: hsl(var(--surface-muted));
|
||||||
position: relative;
|
border-top: 1px solid hsl(var(--border));
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-content {
|
.footer-content {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-headline {
|
.footer-headline {
|
||||||
font-size: 2rem;
|
font-size: 1.9rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--pixel-white);
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 1rem 0;
|
margin: 0 0 0.75rem 0;
|
||||||
text-shadow: 2px 2px 0 var(--pixel-shadow-dark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-tagline {
|
.footer-tagline {
|
||||||
font-size: 1.125rem;
|
font-size: 1.05rem;
|
||||||
color: var(--pixel-bg-light);
|
color: hsl(var(--text-secondary));
|
||||||
margin: 0 0 2.5rem 0;
|
margin: 0 0 2rem 0;
|
||||||
opacity: 0.9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-login-buttons {
|
.footer-login-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-tech {
|
.footer-tech {
|
||||||
font-size: 0.875rem;
|
font-size: 0.9rem;
|
||||||
color: var(--pixel-text-muted);
|
color: hsl(var(--text-muted));
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,23 +365,17 @@
|
|||||||
Responsive Design
|
Responsive Design
|
||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
/* Tablet (768px+) */
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.hero-brand {
|
|
||||||
font-size: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-headline {
|
.hero-headline {
|
||||||
font-size: 3rem;
|
font-size: 3.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-tagline {
|
.hero-tagline {
|
||||||
font-size: 1.5rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-login-buttons {
|
.provider-buttons {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 1.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.features-grid {
|
.features-grid {
|
||||||
@@ -328,48 +383,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 3rem;
|
font-size: 2.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Desktop (1024px+) */
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.hero-brand {
|
.hero-grid {
|
||||||
font-size: 4.5rem;
|
grid-template-columns: 1.05fr 0.95fr;
|
||||||
}
|
|
||||||
|
|
||||||
.hero-headline {
|
|
||||||
font-size: 3.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.features-grid {
|
.features-grid {
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card {
|
|
||||||
padding: 2rem 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Large Desktop (1280px+) */
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.hero-headline {
|
|
||||||
font-size: 4rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reduced Motion */
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.landing-hero {
|
.landing-login-button,
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-scroll-hint {
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card {
|
.feature-card {
|
||||||
animation: none;
|
transition: none;
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,21 @@ function LandingPage() {
|
|||||||
<div className="landing-page">
|
<div className="landing-page">
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="landing-hero">
|
<section className="landing-hero">
|
||||||
<FloatingGem position={{ top: '10%', left: '8%' }} delay={0} size={44} />
|
<div className="hero-gem hero-gem-one">
|
||||||
<FloatingGem position={{ top: '15%', right: '12%' }} delay={1.5} size={36} />
|
<FloatingGem position={{ top: '12%', left: '8%' }} delay={0} size={28} />
|
||||||
<FloatingGem position={{ top: '45%', left: '5%' }} delay={2.5} size={28} />
|
</div>
|
||||||
<FloatingGem position={{ bottom: '25%', right: '8%' }} delay={3.5} size={40} />
|
<div className="hero-gem hero-gem-two">
|
||||||
<FloatingGem position={{ bottom: '15%', left: '15%' }} delay={4} size={32} />
|
<FloatingGem position={{ bottom: '18%', right: '10%' }} delay={1.5} size={24} />
|
||||||
<FloatingGem position={{ top: '60%', right: '20%' }} delay={1} size={24} />
|
|
||||||
|
|
||||||
<div className="hero-content">
|
|
||||||
<div className="hero-logo">
|
|
||||||
<PixelIcon name="gem" size={56} color="var(--pixel-yellow-gold)" />
|
|
||||||
<h1 className="hero-brand">DocNest</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="hero-headline">Create Together. In Real-Time.</h2>
|
<div className="hero-grid">
|
||||||
|
<div className="hero-content">
|
||||||
|
<div className="hero-logo">
|
||||||
|
<PixelIcon name="gem" size={28} color="hsl(var(--brand-teal))" />
|
||||||
|
<span className="hero-brand">DocNest</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="hero-headline">Create together. In real time.</h1>
|
||||||
<p className="hero-tagline">
|
<p className="hero-tagline">
|
||||||
Collaborative documents and Kanban boards that sync instantly.
|
Collaborative documents and Kanban boards that sync instantly.
|
||||||
<br />
|
<br />
|
||||||
@@ -37,22 +38,71 @@ function LandingPage() {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="hero-login-buttons">
|
<div className="hero-login-buttons">
|
||||||
<button className="landing-login-button google" onClick={handleGoogleLogin}>
|
<button className="landing-login-button primary" onClick={handleGoogleLogin}>
|
||||||
|
Get started free
|
||||||
|
<PixelIcon name="gem" size={16} color="white" />
|
||||||
|
</button>
|
||||||
|
<div className="provider-buttons">
|
||||||
|
<button className="landing-login-button provider" onClick={handleGoogleLogin}>
|
||||||
<GoogleIcon />
|
<GoogleIcon />
|
||||||
<span>Sign in with Google</span>
|
<span>Continue with Google</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="landing-login-button github" onClick={handleGitHubLogin}>
|
<button className="landing-login-button provider" onClick={handleGitHubLogin}>
|
||||||
<GitHubIcon />
|
<GitHubIcon />
|
||||||
<span>Sign in with GitHub</span>
|
<span>Continue with GitHub</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="hero-note">No credit card required.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="hero-scroll-hint">
|
<div className="hero-mock">
|
||||||
<PixelIcon name="back-arrow" size={24} style={{ transform: 'rotate(-90deg)' }} />
|
<div className="mock-topbar">
|
||||||
|
<div className="mock-dot" />
|
||||||
|
<div className="mock-dot" />
|
||||||
|
<div className="mock-dot" />
|
||||||
|
</div>
|
||||||
|
<div className="mock-body">
|
||||||
|
<div className="mock-tabs">
|
||||||
|
<span className="mock-tab active">Docs</span>
|
||||||
|
<span className="mock-tab">Boards</span>
|
||||||
|
<span className="mock-tab">History</span>
|
||||||
|
</div>
|
||||||
|
<div className="mock-grid">
|
||||||
|
<div className="mock-card">
|
||||||
|
<div className="mock-line wide" />
|
||||||
|
<div className="mock-line" />
|
||||||
|
<div className="mock-line short" />
|
||||||
|
</div>
|
||||||
|
<div className="mock-card">
|
||||||
|
<div className="mock-line wide" />
|
||||||
|
<div className="mock-line" />
|
||||||
|
<div className="mock-line short" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mock-rows">
|
||||||
|
<div className="mock-row">
|
||||||
|
<span className="mock-pill" />
|
||||||
|
<span className="mock-line" />
|
||||||
|
<span className="mock-line short" />
|
||||||
|
</div>
|
||||||
|
<div className="mock-row">
|
||||||
|
<span className="mock-pill" />
|
||||||
|
<span className="mock-line" />
|
||||||
|
<span className="mock-line short" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<div className="section-divider">
|
||||||
|
<span className="divider-line" />
|
||||||
|
<PixelIcon name="gem" size={16} color="hsl(var(--brand-teal))" />
|
||||||
|
<span className="divider-line" />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Features Section */}
|
{/* Features Section */}
|
||||||
<section className="landing-features">
|
<section className="landing-features">
|
||||||
<h2 className="section-title">Why DocNest?</h2>
|
<h2 className="section-title">Why DocNest?</h2>
|
||||||
@@ -61,42 +111,44 @@ function LandingPage() {
|
|||||||
icon="sync-arrows"
|
icon="sync-arrows"
|
||||||
title="Real-Time Collaboration"
|
title="Real-Time Collaboration"
|
||||||
description="See changes as they happen. Multiple cursors show who's working where."
|
description="See changes as they happen. Multiple cursors show who's working where."
|
||||||
color="var(--pixel-cyan-bright)"
|
color="hsl(var(--brand-teal))"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon="document"
|
icon="document"
|
||||||
title="Rich Documents"
|
title="Rich Documents"
|
||||||
description="Create formatted documents with headings, lists, and more."
|
description="Create formatted documents with headings, lists, and more."
|
||||||
color="var(--pixel-purple-bright)"
|
color="hsl(var(--brand))"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon="kanban"
|
icon="kanban"
|
||||||
title="Kanban Boards"
|
title="Kanban Boards"
|
||||||
description="Drag-and-drop task management with real-time updates."
|
description="Drag-and-drop task management with real-time updates."
|
||||||
color="var(--pixel-orange-warm)"
|
color="hsl(var(--accent))"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon="shield"
|
icon="shield"
|
||||||
title="Offline Support"
|
title="Offline Support"
|
||||||
description="Your work syncs automatically when you're back online."
|
description="Your work syncs automatically when you're back online."
|
||||||
color="var(--pixel-green-lime)"
|
color="hsl(var(--secondary))"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<div className="section-divider">
|
||||||
|
<span className="divider-line" />
|
||||||
|
<PixelIcon name="gem" size={16} color="hsl(var(--brand-teal))" />
|
||||||
|
<span className="divider-line" />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Footer CTA */}
|
{/* Footer CTA */}
|
||||||
<footer className="landing-footer">
|
<footer className="landing-footer">
|
||||||
<FloatingGem position={{ top: '20%', left: '10%' }} delay={0.5} size={28} />
|
|
||||||
<FloatingGem position={{ bottom: '30%', right: '12%' }} delay={2} size={32} />
|
|
||||||
|
|
||||||
<div className="footer-content">
|
<div className="footer-content">
|
||||||
<h3 className="footer-headline">Ready to collaborate?</h3>
|
<h3 className="footer-headline">Ready to collaborate?</h3>
|
||||||
<p className="footer-tagline">Join thousands of teams creating together.</p>
|
<p className="footer-tagline">Join teams building together in DocNest.</p>
|
||||||
|
|
||||||
<div className="footer-login-buttons">
|
<div className="footer-login-buttons">
|
||||||
<button className="landing-login-button google large" onClick={handleGoogleLogin}>
|
<button className="landing-login-button primary large" onClick={handleGoogleLogin}>
|
||||||
<GoogleIcon />
|
Get started free
|
||||||
<span>Get Started Free</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,15 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: var(--gradient-hero);
|
||||||
padding: 20px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-container {
|
.login-container {
|
||||||
background: white;
|
background: hsl(var(--surface));
|
||||||
border-radius: 16px;
|
border-radius: var(--radius-lg);
|
||||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
border: 1px solid hsl(var(--border));
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
padding: 48px 40px;
|
padding: 48px 40px;
|
||||||
max-width: 440px;
|
max-width: 440px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -20,20 +21,20 @@
|
|||||||
.login-title {
|
.login-title {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1a202c;
|
color: hsl(var(--text-primary));
|
||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-subtitle {
|
.login-subtitle {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #718096;
|
color: hsl(var(--text-secondary));
|
||||||
margin: 0 0 32px 0;
|
margin: 0 0 32px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-buttons {
|
.login-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-button {
|
.login-button {
|
||||||
@@ -41,14 +42,22 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 14px 24px;
|
padding: 12px 20px;
|
||||||
font-size: 16px;
|
font-size: 15px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border: none;
|
border: 1px solid hsl(var(--border));
|
||||||
border-radius: 8px;
|
border-radius: var(--radius-md);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background: hsl(var(--surface));
|
||||||
|
color: hsl(var(--text-primary));
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-icon {
|
.button-icon {
|
||||||
@@ -57,27 +66,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.google-button {
|
.google-button {
|
||||||
background: #4285f4;
|
background: var(--gradient-accent);
|
||||||
color: white;
|
color: white;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.google-button:hover {
|
.google-button:hover {
|
||||||
background: #357ae8;
|
filter: brightness(0.98);
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 4px 12px rgba(66, 133, 244, 0.3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.github-button {
|
.github-button {
|
||||||
background: #24292e;
|
background: hsl(var(--surface));
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.github-button:hover {
|
|
||||||
background: #1a1f23;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 4px 12px rgba(36, 41, 46, 0.3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-button:active {
|
.login-button:active {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ function LoginPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="login-page">
|
<div className="login-page">
|
||||||
<div className="login-container">
|
<div className="login-container">
|
||||||
<h1 className="login-title">Realtime Collab</h1>
|
<h1 className="login-title">DocNest</h1>
|
||||||
<p className="login-subtitle">Collaborate in real-time with your team</p>
|
<p className="login-subtitle">Collaborate in real time with your team</p>
|
||||||
|
|
||||||
<div className="login-buttons">
|
<div className="login-buttons">
|
||||||
<button
|
<button
|
||||||
@@ -61,7 +61,7 @@ function LoginPage() {
|
|||||||
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Sign in with Google
|
Continue with Google
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@@ -74,7 +74,7 @@ function LoginPage() {
|
|||||||
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z"
|
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Sign in with GitHub
|
Continue with GitHub
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,38 +11,50 @@ export default {
|
|||||||
ring: 'hsl(var(--ring))',
|
ring: 'hsl(var(--ring))',
|
||||||
background: 'hsl(var(--background))',
|
background: 'hsl(var(--background))',
|
||||||
foreground: 'hsl(var(--foreground))',
|
foreground: 'hsl(var(--foreground))',
|
||||||
primary: { DEFAULT: '#8B4FB9', foreground: '#FFFFFF' },
|
primary: { DEFAULT: 'hsl(var(--primary))', foreground: 'hsl(var(--primary-foreground))' },
|
||||||
secondary: { DEFAULT: '#00D9FF', foreground: '#2B1B38' },
|
secondary: { DEFAULT: 'hsl(var(--secondary))', foreground: 'hsl(var(--secondary-foreground))' },
|
||||||
accent: { DEFAULT: '#FF6EC7', foreground: '#FFFFFF' },
|
accent: { DEFAULT: 'hsl(var(--accent))', foreground: 'hsl(var(--accent-foreground))' },
|
||||||
muted: { DEFAULT: '#F5F0FF', foreground: '#4A3B5C' },
|
muted: { DEFAULT: 'hsl(var(--muted))', foreground: 'hsl(var(--muted-foreground))' },
|
||||||
|
surface: {
|
||||||
|
DEFAULT: 'hsl(var(--surface))',
|
||||||
|
muted: 'hsl(var(--surface-muted))',
|
||||||
|
},
|
||||||
|
brand: {
|
||||||
|
DEFAULT: 'hsl(var(--brand))',
|
||||||
|
dark: 'hsl(var(--brand-dark))',
|
||||||
|
teal: 'hsl(var(--brand-teal))',
|
||||||
|
tealDark: 'hsl(var(--brand-teal-dark))',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: 'hsl(var(--text-primary))',
|
||||||
|
secondary: 'hsl(var(--text-secondary))',
|
||||||
|
muted: 'hsl(var(--text-muted))',
|
||||||
|
},
|
||||||
|
|
||||||
// Custom pixel palette
|
// Legacy pixel palette aliases (mapped to modern tokens)
|
||||||
pixel: {
|
pixel: {
|
||||||
purple: { deep: '#4A1B6F', bright: '#8B4FB9' },
|
purple: { deep: '#1E40AF', bright: '#2563EB' },
|
||||||
cyan: { bright: '#00D9FF' },
|
cyan: { bright: '#14B8A6' },
|
||||||
pink: { vibrant: '#FF6EC7' },
|
pink: { vibrant: '#38BDF8' },
|
||||||
orange: { warm: '#FF8E3C' },
|
orange: { warm: '#F59E0B' },
|
||||||
yellow: { gold: '#FFD23F' },
|
yellow: { gold: '#FBBF24' },
|
||||||
green: { lime: '#8EF048', forest: '#3FA54D' },
|
green: { lime: '#22C55E', forest: '#16A34A' },
|
||||||
bg: { dark: '#2B1B38', medium: '#4A3B5C', light: '#E8D9F3' },
|
bg: { dark: '#0F172A', medium: '#1E293B', light: '#F5F7FB' },
|
||||||
panel: '#F5F0FF',
|
panel: '#FFFFFF',
|
||||||
white: '#FFFFFF',
|
white: '#FFFFFF',
|
||||||
shadow: { dark: '#1A0E28' },
|
shadow: { dark: 'rgba(15, 23, 42, 0.2)' },
|
||||||
outline: '#2B1B38',
|
outline: '#E2E8F0',
|
||||||
text: { primary: '#2B1B38', secondary: '#4A3B5C', muted: '#8B7B9C' },
|
text: { primary: '#0F172A', secondary: '#334155', muted: '#64748B' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
pixel: ['"Press Start 2P"', 'cursive'],
|
display: ['"Manrope"', 'Inter', 'sans-serif'],
|
||||||
sans: ['-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', 'sans-serif'],
|
sans: ['"Inter"', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', 'sans-serif'],
|
||||||
},
|
},
|
||||||
boxShadow: {
|
boxShadow: {
|
||||||
'pixel-sm': '3px 3px 0 #1A0E28',
|
'soft': 'var(--shadow-sm)',
|
||||||
'pixel': '4px 4px 0 #1A0E28, 4px 4px 0 3px #2B1B38',
|
'card': 'var(--shadow-md)',
|
||||||
'pixel-md': '6px 6px 0 #1A0E28, 6px 6px 0 3px #2B1B38',
|
'float': 'var(--shadow-lg)',
|
||||||
'pixel-lg': '8px 8px 0 #1A0E28, 8px 8px 0 3px #2B1B38',
|
|
||||||
'pixel-hover': '5px 5px 0 #1A0E28',
|
|
||||||
'pixel-active': '2px 2px 0 #1A0E28',
|
|
||||||
},
|
},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
'pixel-float': {
|
'pixel-float': {
|
||||||
@@ -61,10 +73,10 @@ export default {
|
|||||||
'pixel-bounce': 'pixel-bounce 1s ease-in-out infinite',
|
'pixel-bounce': 'pixel-bounce 1s ease-in-out infinite',
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
DEFAULT: '0',
|
DEFAULT: 'var(--radius-md)',
|
||||||
lg: '0',
|
lg: 'var(--radius-lg)',
|
||||||
md: '0',
|
md: 'var(--radius-md)',
|
||||||
sm: '0',
|
sm: 'var(--radius-sm)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user