Skip to content

Commit

Permalink
feat(SelectableCard): gallery variant and some improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
marcinsawicki committed Nov 29, 2024
1 parent 7877a0d commit b10b3e4
Show file tree
Hide file tree
Showing 16 changed files with 422 additions and 131 deletions.
4 changes: 4 additions & 0 deletions packages/react-components/src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export interface AvatarProps extends ComponentCoreProps {
* Displays rim
*/
withRim?: boolean;
/**
* Custom style for the avatar
*/
style?: React.CSSProperties;
}

const baseClass = 'avatar';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ $base-class: 'selectable-card';

.#{$base-class} {
display: flex;
transition: border-color var(--transition-duration-fast-2) ease-in-out;
position: relative;
transition:
border-color var(--transition-duration-fast-2) ease-in-out,
box-shadow var(--transition-duration-fast-2) ease-in-out;
border: 1px solid var(--border-basic-secondary);
border-radius: var(--radius-3);
box-shadow: 0;
background: var(--surface-primary-default);
width: max-content;

&:hover {
border-color: var(--border-basic-hover);
box-shadow: var(--shadow-float);
cursor: pointer;
}

Expand All @@ -20,10 +25,20 @@ $base-class: 'selectable-card';

&--thumbnail {
padding: var(--spacing-3) var(--spacing-5);

.#{$base-class}__select-indicator {
margin-right: var(--spacing-2);
}
}

&--gallery {
padding: var(--spacing-5);

.#{$base-class}__select-indicator {
position: absolute;
top: 9px;
left: 12px;
}
}

&--interactive {
Expand All @@ -34,12 +49,12 @@ $base-class: 'selectable-card';
&--selected,
&--selected:hover {
border-color: var(--action-primary-default);
box-shadow: var(--shadow-float);
}

&__select-indicator {
display: flex;
align-items: center;
margin-right: var(--spacing-2);
height: 21px;

&__checkbox {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.custom-element {
.thumbnail-custom-element {
display: flex;
flex-direction: column;
align-items: center;
Expand All @@ -10,3 +10,19 @@
color: var(--content-subtle);
font-size: 12px;
}

.gallery-custom-element {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px dashed var(--border-default);
border-radius: var(--radius-1);
background-color: var(--surface-basic-subtle);
padding: var(--spacing-2);
width: 100px;
height: 100px;
text-align: center;
color: var(--content-subtle);
font-size: 12px;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { Meta } from '@storybook/react';

import { StoryDescriptor } from '../../stories/components/StoryDescriptor';

import { SelectableCard } from './SelectableCard';
import { CheckboxCards, RadioCards } from './SelectableCard.stories.components';

import './SelectableCard.stories.css';

Expand All @@ -12,36 +9,8 @@ export default {
component: SelectableCard,
} as Meta<typeof SelectableCard>;

export const ThumbnailSelectableCardAsRadioType = () => (
<>
<StoryDescriptor title="With Label">
<RadioCards />
</StoryDescriptor>
<StoryDescriptor title="With Label, Description">
<RadioCards withDescription />
</StoryDescriptor>
<StoryDescriptor title="With Label, Description and Icon">
<RadioCards withDescription withIcon />
</StoryDescriptor>
<StoryDescriptor title="With Custom element">
<RadioCards withDescription withIcon withCustomElement />
</StoryDescriptor>
</>
);

export const ThumbnailSelectableCardAsCheckboxType = () => (
<>
<StoryDescriptor title="With Label">
<CheckboxCards />
</StoryDescriptor>
<StoryDescriptor title="With Label, Description">
<CheckboxCards withDescription />
</StoryDescriptor>
<StoryDescriptor title="With Label, Description and Icon">
<CheckboxCards withDescription withIcon />
</StoryDescriptor>
<StoryDescriptor title="With Custom element">
<CheckboxCards withDescription withIcon withCustomElement />
</StoryDescriptor>
</>
export const Default = () => (
<SelectableCard selectionType="radio" onClick={() => {}}>
test
</SelectableCard>
);
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ const baseClass = 'selectable-card';
export const SelectableCard: FC<ISelectableCardProps> = ({
children,
className,
kind,
kind = 'interactive',
selectionType,
isSelected = false,
onClick,
style,
}) => {
const mergedClassName = cx(
styles[baseClass],
Expand Down Expand Up @@ -54,6 +55,7 @@ export const SelectableCard: FC<ISelectableCardProps> = ({
className={mergedClassName}
onClick={handleInteractiveClick}
onKeyDown={handleOnKeyDown}
style={style}
>
<div className={styles[`${baseClass}__select-indicator`]}>
{selectionType === 'radio' ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import * as React from 'react';

import {
Palette,
Building,
AccountCircle,
Group,
} from '@livechat/design-system-icons';

import { Icon } from '../../../Icon';

import { GallerySelectableCard } from './GallerySelectableCard';

const ICONS = [Palette, Building, AccountCircle, Group];

interface IRadioCardsProps {
withIcon?: boolean;
withCustomElement?: boolean;
}

const getComponent = (
index: number,
isSelected: boolean,
setSelectedIndex: (index: number) => void,
withIcon: boolean | undefined,
withCustomElement: boolean | undefined,
type: 'radio' | 'checkbox'
) => (
<GallerySelectableCard
key={index}
label={`Card ${index + 1}`}
selectionType={type}
isSelected={isSelected}
onClick={() => setSelectedIndex(index)}
{...(withIcon && { icon: <Icon size="xlarge" source={ICONS[index]} /> })}
{...(withCustomElement && {
customElement: (
<div className="gallery-custom-element">
<Icon size="small" source={ICONS[index]} />
<div>{`Custom element ${index + 1}`}</div>
</div>
),
})}
/>
);

export const RadioCards: React.FC<IRadioCardsProps> = ({
withIcon,
withCustomElement,
}) => {
const [selectedIndex, setSelectedIndex] = React.useState<number>(0);

return [...Array(4)].map((_, index) =>
getComponent(
index,
selectedIndex === index,
setSelectedIndex,
withIcon,
withCustomElement,
'radio'
)
);
};

interface ICheckboxCardsProps {
withIcon?: boolean;
withCustomElement?: boolean;
}

export const CheckboxCards: React.FC<ICheckboxCardsProps> = ({
withIcon,
withCustomElement,
}) => {
const [selectedIndex, setSelectedIndex] = React.useState<number[]>([]);

const handleCardClick = (index: number) => {
if (selectedIndex.includes(index)) {
setSelectedIndex(selectedIndex.filter((selected) => selected !== index));
} else {
setSelectedIndex([...selectedIndex, index]);
}
};

return [...Array(4)].map((_, index) =>
getComponent(
index,
selectedIndex.includes(index),
handleCardClick,
withIcon,
withCustomElement,
'checkbox'
)
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
$base-class: 'gallery-selectable-card';

.#{$base-class} {
display: flex;
align-items: center;
justify-content: center;
min-width: 60px;
min-height: 72px;

&__label {
position: absolute;
top: 100%;
margin-top: var(--spacing-1);
text-align: center;
color: var(--content-basic-secondary);
}
}
Loading

0 comments on commit b10b3e4

Please sign in to comment.