mirror of
https://github.com/DocNR/POWR.git
synced 2025-04-19 10:51:19 +00:00
android ui bugs
This commit is contained in:
parent
43df1aeb79
commit
ea5dde32f4
@ -14,6 +14,7 @@ import { FilterSheet, type FilterOptions, type SourceType } from '@/components/l
|
||||
import { useWorkoutStore } from '@/stores/workoutStore';
|
||||
import { generateId } from '@/utils/ids';
|
||||
import { useNDKStore } from '@/lib/stores/ndk';
|
||||
import { useIconColor } from '@/lib/theme/iconUtils';
|
||||
|
||||
// Default available filters
|
||||
const availableFilters = {
|
||||
@ -35,7 +36,8 @@ export default function ExercisesScreen() {
|
||||
const [filterSheetOpen, setFilterSheetOpen] = useState(false);
|
||||
const [currentFilters, setCurrentFilters] = useState<FilterOptions>(initialFilters);
|
||||
const [activeFilters, setActiveFilters] = useState(0);
|
||||
|
||||
const { getIconProps } = useIconColor();
|
||||
|
||||
// Exercise sheet state
|
||||
const [showExerciseSheet, setShowExerciseSheet] = useState(false);
|
||||
const [exerciseToEdit, setExerciseToEdit] = useState<ExerciseDisplay | undefined>(undefined);
|
||||
@ -200,36 +202,37 @@ export default function ExercisesScreen() {
|
||||
|
||||
return (
|
||||
<View className="flex-1 bg-background">
|
||||
{/* Search bar with filter button */}
|
||||
<View className="px-4 py-2 border-b border-border">
|
||||
<View className="flex-row items-center">
|
||||
<View className="relative flex-1">
|
||||
<View className="absolute left-3 z-10 h-full justify-center">
|
||||
<Search size={18} className="text-muted-foreground" />
|
||||
</View>
|
||||
<Input
|
||||
value={searchQuery}
|
||||
onChangeText={setSearchQuery}
|
||||
placeholder="Search exercises"
|
||||
className="pl-9 pr-10 bg-muted/50 border-0"
|
||||
/>
|
||||
<View className="absolute right-2 z-10 h-full justify-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onPress={() => setFilterSheetOpen(true)}
|
||||
>
|
||||
<View className="relative">
|
||||
<ListFilter className="text-muted-foreground" size={20} />
|
||||
{activeFilters > 0 && (
|
||||
<View className="absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full" style={{ backgroundColor: '#f7931a' }} />
|
||||
)}
|
||||
{/* Search bar with filter button */}
|
||||
<View className="px-4 py-2 border-b border-border">
|
||||
<View className="flex-row items-center">
|
||||
<View className="relative flex-1">
|
||||
<View className="absolute left-3 z-10 h-full justify-center">
|
||||
<Search size={18} {...getIconProps('primary')} />
|
||||
</View>
|
||||
</Button>
|
||||
<Input
|
||||
value={searchQuery}
|
||||
onChangeText={setSearchQuery}
|
||||
placeholder="Search exercises"
|
||||
className="pl-9 pr-10 border-0 bg-background"
|
||||
/>
|
||||
<View className="absolute right-2 z-10 h-full justify-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onPress={() => setFilterSheetOpen(true)}
|
||||
>
|
||||
<View className="relative">
|
||||
<ListFilter size={20} {...getIconProps('primary')} />
|
||||
{activeFilters > 0 && (
|
||||
<View className="absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full" style={{ backgroundColor: '#f7931a' }} />
|
||||
)}
|
||||
</View>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
{/* Filter Sheet */}
|
||||
<FilterSheet
|
||||
|
@ -1,47 +0,0 @@
|
||||
// components/library/SearchPopover.tsx
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Search, X } from 'lucide-react-native';
|
||||
|
||||
interface SearchPopoverProps {
|
||||
searchQuery: string;
|
||||
onSearchChange: (query: string) => void;
|
||||
}
|
||||
|
||||
export function SearchPopover({ searchQuery, onSearchChange }: SearchPopoverProps) {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
return (
|
||||
<Popover onOpenChange={setIsOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<Search className="text-foreground" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80 p-0" align="end">
|
||||
<View className="flex-row items-center p-2 gap-2">
|
||||
<Input
|
||||
placeholder="Search exercises..."
|
||||
value={searchQuery}
|
||||
onChangeText={onSearchChange}
|
||||
className="flex-1"
|
||||
autoFocus
|
||||
placeholderTextColor="text-muted-foreground"
|
||||
/>
|
||||
{searchQuery.length > 0 && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onPress={() => onSearchChange('')}
|
||||
>
|
||||
<X size={20} className="text-muted-foreground" />
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
134
docs/design/styling_design_doc.md
Normal file
134
docs/design/styling_design_doc.md
Normal file
@ -0,0 +1,134 @@
|
||||
# POWR App Styling Guide
|
||||
|
||||
This document outlines how to consistently style components in the POWR fitness app.
|
||||
|
||||
## Color System
|
||||
|
||||
All colors are defined in the theme system and should be accessed through it rather than hardcoded values.
|
||||
|
||||
### Import Path
|
||||
|
||||
```typescript
|
||||
import { useIconColor } from '@/lib/theme/iconUtils';
|
||||
import { FIXED_COLORS } from '@/lib/theme/colors';
|
||||
Icon Styling
|
||||
Icons must use the icon utility to ensure visibility on both iOS and Android:
|
||||
typescriptCopy// Import icon utility
|
||||
import { useIconColor } from '@/lib/theme/iconUtils';
|
||||
|
||||
// Inside your component
|
||||
const { getIconProps, getIconColor } = useIconColor();
|
||||
|
||||
// Apply to icons
|
||||
<Icon
|
||||
size={24}
|
||||
{...getIconProps('primary')} // Use appropriate variant
|
||||
/>
|
||||
Icon Variants
|
||||
|
||||
primary - For main actions and interactive elements (purple)
|
||||
muted - For secondary or less important actions (gray)
|
||||
destructive - For delete/remove actions (red)
|
||||
success - For confirmation/complete actions (green)
|
||||
warning - For caution indicators (yellow/orange)
|
||||
|
||||
Examples
|
||||
tsxCopy// Primary action icon
|
||||
<Play {...getIconProps('primary')} size={20} />
|
||||
|
||||
// Destructive action icon
|
||||
<Trash2 {...getIconProps('destructive')} size={20} />
|
||||
|
||||
// Icon with custom fill
|
||||
<Star
|
||||
{...getIconProps(isFavorite ? 'primary' : 'muted')}
|
||||
fill={isFavorite ? getIconColor('primary') : "none"}
|
||||
size={20}
|
||||
/>
|
||||
Button Styling
|
||||
Use the standard button component with appropriate variants:
|
||||
tsxCopy// Primary button
|
||||
<Button variant="default" className="w-full">
|
||||
<Text className="text-primary-foreground">Primary Action</Text>
|
||||
</Button>
|
||||
|
||||
// Destructive button
|
||||
<Button variant="destructive" className="w-full">
|
||||
<Text className="text-destructive-foreground">Delete</Text>
|
||||
</Button>
|
||||
|
||||
// Outline button
|
||||
<Button variant="outline" className="w-full">
|
||||
<Text>Secondary Action</Text>
|
||||
</Button>
|
||||
Header Component
|
||||
Use the Header component consistently:
|
||||
tsxCopy// Standard header with title
|
||||
<Header title="Screen Title" showNotifications={true} />
|
||||
|
||||
// Header with logo
|
||||
<Header useLogo={true} showNotifications={true} />
|
||||
|
||||
// Header with custom right element
|
||||
<Header
|
||||
title="Screen Title"
|
||||
rightElement={<YourCustomElement />}
|
||||
/>
|
||||
Text Styling
|
||||
Use the Text component with appropriate Tailwind classes:
|
||||
tsxCopy// Headings
|
||||
<Text className="text-xl font-semibold text-foreground">Heading</Text>
|
||||
|
||||
// Body text
|
||||
<Text className="text-base text-foreground">Regular text</Text>
|
||||
|
||||
// Secondary text
|
||||
<Text className="text-sm text-muted-foreground">Secondary text</Text>
|
||||
Card Components
|
||||
Use the Card component for content blocks:
|
||||
tsxCopy<Card className="mx-4">
|
||||
<CardContent className="p-4">
|
||||
{/* Card content */}
|
||||
</CardContent>
|
||||
</Card>
|
||||
Dialog/Alert Styling
|
||||
Center buttons in dialogs:
|
||||
tsxCopy<AlertDialog>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
<Text>Alert Title</Text>
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<Text>Alert description text.</Text>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<View className="flex-row justify-center gap-3">
|
||||
<AlertDialogCancel>
|
||||
<Text>Cancel</Text>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction className="bg-destructive">
|
||||
<Text className="text-destructive-foreground">Confirm</Text>
|
||||
</AlertDialogAction>
|
||||
</View>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
Best Practices
|
||||
|
||||
Never use hardcoded colors - Always use theme variables through Tailwind classes
|
||||
Always use getIconProps for icons - Ensures visibility on both iOS and Android
|
||||
Use semantic variants - Choose button and icon variants based on their purpose
|
||||
Maintain consistent spacing - Use Tailwind spacing classes (p-4, m-2, etc.)
|
||||
Check both platforms - Test UI changes on both iOS and Android
|
||||
|
||||
Troubleshooting
|
||||
If icons aren't appearing on Android:
|
||||
|
||||
Ensure you're using getIconProps() instead of className for the icon
|
||||
Add strokeWidth={2} for better visibility on Android
|
||||
Check that the icon has a size specified
|
||||
|
||||
If colors seem inconsistent:
|
||||
|
||||
Verify you're using Tailwind classes (text-primary vs #8B5CF6)
|
||||
Check that the correct variant is being used for your component
|
Loading…
x
Reference in New Issue
Block a user