Skip to content

Commit

Permalink
feat: Minor updates to Range, showcase improvements (#29)
Browse files Browse the repository at this point in the history
Co-authored-by: Anand Gorantala <[email protected]>
  • Loading branch information
anandgorantala and anandgorantala authored Nov 15, 2024
1 parent 92538c1 commit 2dfdfab
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 70 deletions.
127 changes: 116 additions & 11 deletions src/components/product-card/product-card.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Meta, StoryObj } from '@storybook/react';
import { CSSProperties, useState } from 'react';
import { CSSProperties, useMemo, useState } from 'react';

import { ProductCard } from './';
import { ProductCardRoot } from './components/product-card-root';
Expand Down Expand Up @@ -91,7 +91,7 @@ export const Basic: Story = {
<ProductCard.Title>{product.title}</ProductCard.Title>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -120,7 +120,7 @@ export const Simple: Story = {
<ProductCard.SubTitle>{product.collection}</ProductCard.SubTitle>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} />
<ProductCard.Price price={product.price} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -163,7 +163,7 @@ export const TextSwatches: Story = {
</SwatchBar.Root>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -210,7 +210,7 @@ export const ColorSwatches: Story = {
</SwatchBar.Root>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -260,7 +260,7 @@ export const ImageSwatches: Story = {
<ProductCard.Title>{product.title}</ProductCard.Title>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} />
<ProductCard.Price price={product.price} />
<ProductCard.Button variant="primary">View options &rsaquo;</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -289,7 +289,7 @@ export const BadgesAndFavoriteBtn: Story = {
<ProductCard.SubTitle>{product.collection}</ProductCard.SubTitle>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.PriceRange currency={product.currency} from={product.price} to={product.price + 100} />
<ProductCard.PriceRange from={product.price} to={product.price + 100} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -338,7 +338,7 @@ export const RTL: Story = {
<ProductCard.Title>{product.title}</ProductCard.Title>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} />
<ProductCard.Price price={product.price} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -399,7 +399,7 @@ export const Themes: Story = {
</SwatchBar.Root>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down Expand Up @@ -436,7 +436,7 @@ export const Themes: Story = {
</SwatchBar.Root>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand All @@ -449,6 +449,111 @@ export const Themes: Story = {
},
};

/**
* Composable and i18n ready
*/
export const Locales: Story = {
render: (args) => {
const [sku, setSku] = useState<string | undefined>();
const [preview, setPreview] = useState<string | undefined>();

function setSwatch(id: string) {
setSku(id);
setPreview(product.variants.find(v => v.id === id)?.image);
}

const variations = useMemo(() => {
return [{
dir: 'ltr',
locale: 'en-US',
currency: 'USD',
title: 'Limitless Shirt',
subtitle: 'Apparel',
atc: 'Add to cart',
}, {
dir: 'ltr',
locale: 'nl-NL',
currency: 'EUR',
title: 'Grenzeloos overhemd',
subtitle: 'Kleding',
atc: 'Voeg toe aan winkelwagen',
}, {
dir: 'ltr',
locale: 'sk-SK',
currency: 'EUR',
title: 'Neobmedzená košeľa',
subtitle: 'Oblečenie',
atc: 'Pridať do košíka',
}, {
locale: 'ar-AE',
dir: 'rtl',
currency: 'AED',
title: 'قميص لا حدود له',
subtitle: 'ملابس',
atc: 'أضف إلى السلة',
}, {
dir: 'ltr',
locale: 'hi-IN',
currency: 'INR',
title: 'असीमित शर्ट',
subtitle: 'परिधान',
atc: 'कार्ट में जोड़ें',
}, {
dir: 'ltr',
locale: 'zh-CN',
currency: 'CNY',
title: '無限襯衫',
subtitle: '服飾',
atc: '加入購物車',
}, {
dir: 'rtl',
locale: 'jp-JP',
currency: 'JPY',
title: 'リミットレスシャツ',
subtitle: '衣服',
atc: 'カートに追加',
}];
}, []);

return (
<div style={{display: 'flex', gap: '1rem', flexWrap: 'wrap'}}>
{variations.map(variation => (
<Theme style={{width: '250px', display: 'flex'}} currency={variation.currency} locale={variation.locale} dir={variation.dir as 'ltr' | 'rtl'}>
<ProductCard.Root {...args}>
<ProductCard.Header>
<ProductCard.Image src={preview || product.image} alt={product.title} />
</ProductCard.Header>
<ProductCard.Body>
<ProductCard.Badge>{variation.locale}</ProductCard.Badge>
<ProductCard.Title>{variation.title}</ProductCard.Title>
<ProductCard.SubTitle>{variation.subtitle}</ProductCard.SubTitle>
<SwatchBar.Root>
<SwatchBar.SwatchGroup value={sku} onValueChange={(newValue) => setSwatch(newValue)}>
{
product.variants.map((swatch) => {
return <SwatchBar.SwatchImage key={swatch.id} value={swatch.id}>
<img src={swatch.image} alt={swatch.title} />
</SwatchBar.SwatchImage>
})
}
</SwatchBar.SwatchGroup>
</SwatchBar.Root>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">{variation.atc}</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
</Theme>
))}
</div>
);
},
args: {
className: 'custom-class-name',
},
};

/**
* Bring your own components, HTML and CSS to compose the ProductCard to match your needs
*/
Expand All @@ -472,7 +577,7 @@ export const MixCustomHTML: Story = {
<ProductCard.SubTitle>{product.collection}</ProductCard.SubTitle>
</ProductCard.Body>
<ProductCard.Footer>
<ProductCard.Price currency={product.currency} price={product.price} salePrice={product.salePrice} />
<ProductCard.Price price={product.price} salePrice={product.salePrice} />
<ProductCard.Button variant="primary">Add to cart</ProductCard.Button>
</ProductCard.Footer>
</ProductCard.Root>
Expand Down
30 changes: 30 additions & 0 deletions src/components/range/components/range-max-value.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import cn from 'clsx';
import { ForwardedRef, forwardRef, ReactElement } from 'react';
import { Number } from '../../number';

import type { RangeValueProps } from '../range.types';
import { useRange } from '../range.context';

export const RangeMaxValue = forwardRef((
props: RangeValueProps,
forwardedRef: ForwardedRef<HTMLSpanElement> | null,
): ReactElement => {
const rangeCtx = useRange();

if (!rangeCtx) {
throw new Error('Range.MaxValue should be used within a RangeProvider');
}

const { value } = rangeCtx;

const {
className,
...rest
} = props;

return (
<Number {...rest} value={value[1]} className={cn('lui-range-min-value', className)} ref={forwardedRef} />
);
});

RangeMaxValue.displayName = "Range.MaxValue";
30 changes: 30 additions & 0 deletions src/components/range/components/range-min-value.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import cn from 'clsx';
import { ForwardedRef, forwardRef, ReactElement } from 'react';
import { Number } from '../../number';

import type { RangeValueProps } from '../range.types';
import { useRange } from '../range.context';

export const RangeMinValue = forwardRef((
props: RangeValueProps,
forwardedRef: ForwardedRef<HTMLSpanElement> | null,
): ReactElement => {
const rangeCtx = useRange();

if (!rangeCtx) {
throw new Error('Range.MinValue should be used within a RangeProvider');
}

const { value } = rangeCtx;

const {
className,
...rest
} = props;

return (
<Number {...rest} value={value[0]} className={cn('lui-range-min-value', className)} ref={forwardedRef} />
);
});

RangeMinValue.displayName = "Range.MinValue";
7 changes: 6 additions & 1 deletion src/components/range/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { RangeInputs } from "./components/range-inputs";
import { RangeUpdateButton } from "./components/range-update-button";
import { RangeSeparator } from "./components/range-separator";
import { RangeProvider } from "./range.context";
import { RangeMaxValue } from "./components/range-max-value";
import { RangeMinValue } from "./components/range-min-value";

export const Range = {
Root: RangeRoot,
Expand All @@ -15,7 +17,9 @@ export const Range = {
Slider: RangeSlider,
Inputs: RangeInputs,
Separator: RangeSeparator,
UpdateButton: RangeUpdateButton
UpdateButton: RangeUpdateButton,
MinValue: RangeMinValue,
MaxValue: RangeMaxValue,
};

export {
Expand All @@ -30,4 +34,5 @@ export type {
RangeButtonProps,
RangeInputProps,
RangeInputsProps,
RangeValueProps,
} from './range.types';
6 changes: 6 additions & 0 deletions src/components/range/range.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,10 @@
cursor: pointer;
width: 100%;
}

.lui-range-min-value,
.lui-range-max-value {
font-size: 0.875rem;
font-weight: 600;
}
}
9 changes: 9 additions & 0 deletions src/components/range/range.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ export const MixCustomHTML: Story = {
<div style={{display: 'flex', alignItems: 'center', gap: '0.25rem'}}><Range.MaxInput />inches</div>
</Range.Inputs>
</Range.Root>

<Range.Root min={2000} max={8000} value={[3000, 7000]} onChange={() => {}}>
<Range.Slider />
<Range.Inputs>
<Range.MinValue>m</Range.MinValue>
<Range.Separator />
<Range.MaxValue>m</Range.MaxValue>
</Range.Inputs>
</Range.Root>
</Theme>
);
},
Expand Down
8 changes: 8 additions & 0 deletions src/components/range/range.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ export interface RangeButtonProps extends PropsWithChildren, ButtonHTMLAttribute
*/
className?: string;
}


export interface RangeValueProps extends PropsWithChildren, HTMLProps<HTMLSpanElement> {
/**
* Custom class name for the container of the component.
*/
className?: string;
}
Loading

0 comments on commit 2dfdfab

Please sign in to comment.