Skip to content

Commit

Permalink
Improve Browse UI and other misc (#416)
Browse files Browse the repository at this point in the history
  • Loading branch information
Winston-Hsiao authored Sep 23, 2024
1 parent 4f9c375 commit c06e612
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 122 deletions.
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ export SMTP_SENDER_EMAIL=''
export SMTP_PASSWORD=''
export SMTP_SENDER_NAME=''
export SMTP_USERNAME=''

# For Github OAuth
export GITHUB_CLIENT_ID=''
export GITHUB_CLIENT_SECRET=''

# For Google OAuth
export VITE_GOOGLE_CLIENT_ID=''

# For OnShape
export ONSHAPE_ACCESS_KEY=''
export ONSHAPE_SECRET_KEY=''
```

### Google OAuth Configuration
Expand Down
4 changes: 4 additions & 0 deletions env.sh.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ export GITHUB_CLIENT_SECRET=''
# For Google OAuth
export GOOGLE_CLIENT_ID=''
export GOOGLE_CLIENT_SECRET=''

# For OnShape
export ONSHAPE_ACCESS_KEY=''
export ONSHAPE_SECRET_KEY=''
16 changes: 9 additions & 7 deletions frontend/src/components/home/HeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ const HeroSection: React.FC = () => {
className="w-[300px] h-[140px]"
/>
</div>
<p className="text-lg sm:text-xl md:text-2xl text-center md:max-w-2xl mt-4 sm:mt-8">
<p className="text-lg sm:text-xl md:text-2xl text-center md:max-w-2xl mt-4">
Program robots with K-Lang, our language purpose-built for humanoid
robots.
</p>
<Button variant="primary" className="mt-6 sm:mt-10 py-6 px-3">
<Button
variant="primary"
className="mt-6 sm:mt-10 py-6 px-5 hover:bg-white hover:text-primary-9"
>
<div className="flex items-center">
<FaCirclePlay className="mr-2 h-5 w-5" />
<div className="flex flex-col items-start">
<span className="font-medium tracking-widest">Watch Demo</span>
<span className="text-gray-3 font-thin">1 minute</span>
</div>
<FaCirclePlay className="mr-3 h-5 w-5" />
<span className="text-base font-medium tracking-widest">
Watch Demo
</span>
</div>
</Button>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/home/KLangDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ speakPhrase("Hello, I am a robot.");`,
</div>
<div className="mt-6 px-4">
<div className="flex flex-col gap-2 mb-6 text-center">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl md:text-5xl text-gray-1">
<h2 className="text-3xl font-semibold tracking-tight sm:text-4xl md:text-5xl text-gray-1">
Watch <span className="font-black text-primary-9">K-Lang</span> In
Action
</h2>
Expand Down
35 changes: 9 additions & 26 deletions frontend/src/components/listings/ListingGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { useEffect, useState } from "react";
import Masonry from "react-masonry-css";
import { Link } from "react-router-dom";

import ListingGridCard from "@/components/listings/ListingGridCard";
import { Card } from "@/components/ui/Card";
import Spinner from "@/components/ui/Spinner";
import { paths } from "@/gen/api";
import { useAlertQueue } from "@/hooks/useAlertQueue";
Expand Down Expand Up @@ -46,37 +44,22 @@ const ListingGrid = (props: ListingGridProps) => {
}
}, [listingIds]);

const breakpointColumnsObj = {
default: 4,
1536: 3,
1280: 3,
1024: 2,
768: 2,
640: 1,
};

return listingIds === null ? (
<div className="flex justify-center items-center h-64">
<Spinner />
</div>
) : (
<Masonry
breakpointCols={breakpointColumnsObj}
className="flex w-auto -ml-4 sm:-ml-6"
columnClassName="pl-4 sm:pl-6 bg-clip-padding"
>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 sm:gap-6">
{listingIds.map((listingId) => (
<Card key={listingId} className="mb-4 sm:mb-6 overflow-hidden">
<Link to={`/item/${listingId}`}>
<ListingGridCard
listingId={listingId}
listing={listingInfo?.find((l) => l.id === listingId)}
showDescription={true}
/>
</Link>
</Card>
<Link to={`/item/${listingId}`} key={listingId}>
<ListingGridCard
listingId={listingId}
listing={listingInfo?.find((l) => l.id === listingId)}
showDescription={true}
/>
</Link>
))}
</Masonry>
</div>
);
};

Expand Down
56 changes: 24 additions & 32 deletions frontend/src/components/listings/ListingGridCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,34 @@ const ListingGridCard = ({
const getFirstLine = (text: string | null) => {
if (!text) return null;
const firstLine = text.split("\n")[0].trim();
return firstLine.length > 100 ? `${firstLine.slice(0, 97)}...` : firstLine;
return firstLine.length > 60 ? `${firstLine.slice(0, 57)}...` : firstLine;
};

return (
<div className="mb-4 sm:mb-6 bg-white rounded-lg shadow-md overflow-hidden transition-transform duration-300 ease-in-out hover:shadow-lg hover:-translate-y-1">
{listing ? (
<>
{listing.image_url && (
<div className="relative pb-[100%]">
<img
src={listing.image_url}
alt={listing.name}
className="absolute top-0 left-0 w-full h-full object-cover"
/>
</div>
)}
<div className="p-4">
<h3 className="text-lg font-semibold mb-2 text-gray-800">
{listing.name}
</h3>
{showDescription && listing.description !== null && (
<div className="text-sm text-gray-600">
<RenderDescription
description={getFirstLine(listing.description) || ""}
/>
</div>
)}
<div className="bg-white rounded-lg shadow-md overflow-hidden transition-transform duration-300 ease-in-out hover:shadow-lg hover:-translate-y-1 h-auto flex flex-col">
<div className="relative pb-[100%]">
{listing?.image_url ? (
<img
src={listing.image_url}
alt={listing.name}
className="absolute top-0 left-0 w-full h-full object-cover"
/>
) : (
<div className="absolute top-0 left-0 w-full h-full bg-gray-3" />
)}
</div>
<div className="p-3 flex-grow flex flex-col justify-between">
<h3 className="text-base font-semibold mb-1 text-gray-800 line-clamp-1">
{listing?.name || "Loading..."}
</h3>
{showDescription && listing?.description && (
<div className="text-xs text-gray-600 line-clamp-2">
<RenderDescription
description={getFirstLine(listing.description) || ""}
/>
</div>
</>
) : (
<div className="animate-pulse p-4">
<div className="h-6 bg-gray-300 rounded w-3/4 mb-3"></div>
<div className="h-4 bg-gray-300 rounded w-full mb-2"></div>
<div className="h-4 bg-gray-300 rounded w-5/6"></div>
</div>
)}
)}
</div>
</div>
);
};
Expand Down
102 changes: 52 additions & 50 deletions frontend/src/components/pages/Browse.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { FaTimes } from "react-icons/fa";
import { FaChevronLeft, FaChevronRight } from "react-icons/fa";
import { useNavigate, useSearchParams } from "react-router-dom";

import ListingGrid from "@/components/listings/ListingGrid";
Expand Down Expand Up @@ -66,7 +67,6 @@ const Browse = () => {

const prevButton = pageNumber > 1;
const nextButton = moreListings;
const hasButton = prevButton || nextButton;

const options: { value: SortOption; label: string }[] = [
{ value: "most_upvoted", label: "Most Upvoted" },
Expand All @@ -78,29 +78,6 @@ const Browse = () => {
<>
<div className="pb-8">
<div className="flex flex-col md:flex-row justify-center items-center mt-4 gap-y-2 md:gap-x-2">
<div className="w-full md:w-auto">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">
Sort By:{" "}
{options.find((opt) => opt.value === sortOption)?.label}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Sort Options</DropdownMenuLabel>
{options.map((option) => (
<DropdownMenuCheckboxItem
key={option.value}
checked={sortOption === option.value}
onCheckedChange={() => setSortOption(option.value)}
className={`text-gray-11 cursor-pointer ${sortOption === option.value ? "text-gray-12 bg-gray-3" : ""}`}
>
{option.label}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="relative w-full md:w-auto">
<Input
onChange={(e) => {
Expand All @@ -127,36 +104,61 @@ const Browse = () => {
</div>
)}
</div>
<div className="w-full md:w-auto flex flex-col md:flex-row gap-2">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="lg" className="w-full md:w-1/2">
Sort By:{" "}
{options.find((opt) => opt.value === sortOption)?.label}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">
<DropdownMenuLabel>Sort Options</DropdownMenuLabel>
{options.map((option) => (
<DropdownMenuCheckboxItem
key={option.value}
checked={sortOption === option.value}
onCheckedChange={() => setSortOption(option.value)}
className={`text-gray-11 cursor-pointer ${sortOption === option.value ? "text-gray-12 bg-gray-3" : ""}`}
>
{option.label}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
<Button
onClick={() => navigate(`/create`)}
variant="primary"
size="lg"
className="w-full md:w-auto"
>
Create
</Button>
</div>
</div>

<div className="flex justify-between mt-2">
<Button
variant="default"
onClick={() => navigate(`/browse/?page=${pageNumber - 1}`)}
disabled={!prevButton}
>
<div className="flex items-center">
<FaChevronLeft className="text-xs mr-2" />
Previous
</div>
</Button>
<Button
onClick={() => navigate(`/create`)}
variant="primary"
size="lg"
className="w-full md:w-auto"
variant="default"
onClick={() => navigate(`/browse/?page=${pageNumber + 1}`)}
disabled={!nextButton}
>
Create
<div className="flex items-center">
Next
<FaChevronRight className="text-xs ml-2" />
</div>
</Button>
</div>

{hasButton && (
<div className="flex justify-center mt-4">
{prevButton && (
<button
className="bg-gray-3 hover:bg-gray-4 text-gray-12 font-bold py-2 px-4 rounded-l mr-auto"
onClick={() => navigate(`/browse/?page=${pageNumber - 1}`)}
>
Previous
</button>
)}
{nextButton && (
<button
className="bg-gray-3 hover:bg-gray-4 text-gray-12 font-bold py-2 px-4 rounded-r ml-auto"
onClick={() => navigate(`/browse/?page=${pageNumber + 1}`)}
>
Next
</button>
)}
</div>
)}
</div>

<ListingGrid listingIds={listingIds} />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/pages/BuyPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const HeroSection: React.FC = () => {
The future of robotics, now at your fingertips.
</p>
<Button variant="primary" size="lg">
Buy Now - $...
Buy Now
</Button>
</motion.section>
);
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/pages/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const Create = () => {
<div>
<label
htmlFor="name"
className="block mb-2 text-sm font-medium text-gray-11"
className="block mb-2 text-sm font-medium text-gray-12"
>
Name
</label>
Expand All @@ -86,7 +86,7 @@ const Create = () => {
<div className="relative">
<label
htmlFor="description"
className="block mb-2 text-sm font-medium text-gray-11"
className="block mb-2 text-sm font-medium text-gray-12"
>
Description (supports Markdown formatting)
</label>
Expand Down Expand Up @@ -117,7 +117,7 @@ const Create = () => {
{/* Submit */}
<div className="flex justify-end">
<Button variant="primary" type="submit">
Submit
Post build
</Button>
</div>
</form>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Input = React.forwardRef<
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background file:border-0 bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50",
"flex h-10 w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background file:border-0 bg-transparent file:text-sm file:font-medium placeholder:text-gray-10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
Expand All @@ -27,7 +27,7 @@ const TextArea = React.forwardRef<
return (
<textarea
className={cn(
"flex w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background file:border-0 bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"flex w-full rounded-md border border-input px-3 py-2 text-sm ring-offset-background file:border-0 bg-transparent file:text-sm file:font-medium placeholder:text-gray-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
Expand Down

0 comments on commit c06e612

Please sign in to comment.