mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
Better responsive design (#62)
This commit is contained in:
parent
55526e4437
commit
65e38dee4d
6 changed files with 90 additions and 42 deletions
34
.roomodes
Normal file
34
.roomodes
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
customModes:
|
||||
- slug: designer
|
||||
name: 🎨 Designer
|
||||
roleDefinition: >-
|
||||
You are Roo, a UI/UX expert specializing in design systems, user interface design, and frontend development. Your expertise includes:
|
||||
- Creating and maintaining design systems and component libraries
|
||||
- Implementing responsive and accessible web interfaces
|
||||
- Working with CSS, HTML, Tailwind CSS, and modern frontend frameworks like React and Next.js
|
||||
- Ensuring consistent user experiences across platforms and devices
|
||||
- Optimizing user flows and interaction patterns
|
||||
- Creating visually appealing and functional interfaces
|
||||
- Following modern design principles and accessibility standards
|
||||
whenToUse: >-
|
||||
Use this mode when creating or modifying UI components, implementing design systems,
|
||||
working on visual design improvements, ensuring responsive web interfaces, or focusing
|
||||
on user experience enhancements. This mode is especially effective for CSS styling,
|
||||
component design, layout improvements, and frontend framework implementations.
|
||||
groups:
|
||||
- read
|
||||
- edit
|
||||
- browser
|
||||
- command
|
||||
- mcp
|
||||
customInstructions: >-
|
||||
When working in Designer mode, prioritize:
|
||||
- User experience and accessibility
|
||||
- Responsive design principles
|
||||
- Consistent design patterns and component reusability
|
||||
- Modern CSS practices and Tailwind CSS utilities
|
||||
- Clean, semantic HTML structure
|
||||
- Performance optimization for frontend assets
|
||||
- Cross-browser compatibility
|
||||
- Design system consistency
|
||||
Always consider the visual impact and user interaction flow when making changes.
|
||||
|
|
@ -59,7 +59,7 @@ export const Tasks = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
{tasks.map((task) => (
|
||||
<TaskCard
|
||||
key={task.taskId}
|
||||
|
|
|
|||
|
|
@ -27,15 +27,16 @@ export const Usage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-4 sm:gap-6">
|
||||
<UsageCard />
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{viewModes.map((mode) => (
|
||||
<Button
|
||||
key={mode}
|
||||
variant={viewMode === mode ? 'default' : 'secondary'}
|
||||
size="sm"
|
||||
onClick={() => setViewMode(mode)}
|
||||
className="min-w-[80px]"
|
||||
>
|
||||
{t(`view_mode_${mode}`)}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ type MetricProps = {
|
|||
};
|
||||
|
||||
export const Metric = ({ label, value, isPending }: MetricProps) => (
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-secondary bg-background px-3 py-2">
|
||||
<div className="text-xs text-muted-foreground">{label}</div>
|
||||
<div className="font-mono font-semibold text-2xl h-8">
|
||||
<div className="flex flex-col gap-1 rounded-lg border border-secondary bg-background px-2 py-2 sm:px-3 sm:py-3">
|
||||
<div className="text-xs text-muted-foreground line-clamp-1">{label}</div>
|
||||
<div className="font-mono font-semibold text-lg sm:text-xl md:text-2xl h-6 sm:h-7 md:h-8">
|
||||
{isPending ? (
|
||||
<div>
|
||||
<Skeleton className="h-6 w-12 my-1" />
|
||||
<Skeleton className="h-5 w-10 my-1" />
|
||||
</div>
|
||||
) : typeof value === 'number' ? (
|
||||
formatNumber(value)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import {
|
||||
formatNumber,
|
||||
formatCurrency,
|
||||
formatTimestamp,
|
||||
} from '@/lib/formatters';
|
||||
import { formatNumber, formatCurrency } from '@/lib/formatters';
|
||||
import { generateFallbackTitle } from '@/lib/taskUtils';
|
||||
import { Card, CardContent, Button } from '@/components/ui';
|
||||
|
||||
|
|
@ -16,6 +12,27 @@ type TaskCardProps = {
|
|||
onTaskSelected: (task: TaskWithUser) => void;
|
||||
};
|
||||
|
||||
// Helper function for elegant timestamp display
|
||||
const formatElegantTime = (timestamp: number): string => {
|
||||
const date = new Date(timestamp * 1000);
|
||||
const now = new Date();
|
||||
|
||||
// Check if it's today
|
||||
if (date.toDateString() === now.toDateString()) {
|
||||
return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
|
||||
// Check if it's yesterday
|
||||
const yesterday = new Date(now);
|
||||
yesterday.setDate(now.getDate() - 1);
|
||||
if (date.toDateString() === yesterday.toDateString()) {
|
||||
return 'Yesterday';
|
||||
}
|
||||
|
||||
// Otherwise return a short date format
|
||||
return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
|
||||
};
|
||||
|
||||
export const TaskCard = ({ task, onFilter, onTaskSelected }: TaskCardProps) => {
|
||||
return (
|
||||
<Card
|
||||
|
|
@ -23,19 +40,23 @@ export const TaskCard = ({ task, onFilter, onTaskSelected }: TaskCardProps) => {
|
|||
onClick={() => onTaskSelected(task)}
|
||||
>
|
||||
<CardContent className="p-0">
|
||||
<div className="px-4 py-2">
|
||||
{/* First line - Title and Status */}
|
||||
<div className="flex items-center justify-between gap-2 mb-1">
|
||||
<div className="px-4 py-2.5">
|
||||
{/* Line 1: Title and Status */}
|
||||
<div className="flex items-center justify-between gap-2 mb-1.5">
|
||||
<h3 className="font-medium text-sm truncate flex-1 leading-none">
|
||||
{task.title || generateFallbackTitle(task)}
|
||||
</h3>
|
||||
<Status completed={task.completed} />
|
||||
</div>
|
||||
|
||||
{/* Second line - All metadata */}
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-muted-foreground">
|
||||
<div className="flex items-center gap-3">
|
||||
<span>{formatTimestamp(task.timestamp)}</span>
|
||||
{/* Line 2: All metadata in a single line with bullet separators between items */}
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
||||
{/* Left side: Date, User, and Mode (if present) with bullet separators */}
|
||||
<div className="flex items-center">
|
||||
<span className="whitespace-nowrap">
|
||||
{formatElegantTime(task.timestamp)}
|
||||
</span>
|
||||
<div className="mx-2 text-muted-foreground/30">•</div>
|
||||
<Button
|
||||
variant="link"
|
||||
size="sm"
|
||||
|
|
@ -51,33 +72,24 @@ export const TaskCard = ({ task, onFilter, onTaskSelected }: TaskCardProps) => {
|
|||
>
|
||||
{task.user.name}
|
||||
</Button>
|
||||
|
||||
{/* Mode (if present) */}
|
||||
{task.mode && (
|
||||
<span className="px-2 py-1 bg-muted rounded text-xs font-medium">
|
||||
{task.mode}
|
||||
</span>
|
||||
<>
|
||||
<div className="mx-2 text-muted-foreground/30">•</div>
|
||||
<span className="text-xs font-medium text-muted-foreground">
|
||||
{task.mode}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
variant="link"
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onFilter({
|
||||
type: 'model',
|
||||
value: task.model,
|
||||
label: task.model,
|
||||
});
|
||||
}}
|
||||
className="px-0 h-auto text-xs font-normal font-mono text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{task.model}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Metrics on the right */}
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Right side: Tokens and Cost with bullet separator */}
|
||||
<div className="flex items-center whitespace-nowrap">
|
||||
<span className="font-medium">
|
||||
{formatNumber(task.tokens)} tokens
|
||||
</span>
|
||||
<div className="mx-2 text-muted-foreground/30">•</div>
|
||||
<span className="font-medium">{formatCurrency(task.cost)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -64,20 +64,21 @@ export const UsageCard = () => {
|
|||
)}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-row flex-wrap gap-1.5">
|
||||
{timePeriods.map((period) => (
|
||||
<Button
|
||||
key={period}
|
||||
variant={period === timePeriod ? 'default' : 'secondary'}
|
||||
size="sm"
|
||||
onClick={() => setTimePeriod(period)}
|
||||
className="text-xs px-2.5 h-8"
|
||||
>
|
||||
{t(`analytics_period_${period}_days`)}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-5">
|
||||
<div className="grid grid-cols-2 gap-3 lg:grid-cols-5">
|
||||
<Metric
|
||||
label={t('analytics_active_developers')}
|
||||
value={usage[TelemetryEventName.TASK_CREATED]?.users}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue