Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: initial badge component #1004

Merged
merged 31 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a8aaad9
feat: initial badge component
dkonieczek Feb 16, 2024
af8eac5
refactor: separate badge components and wrappers, general cleanup
dkonieczek Feb 22, 2024
781d8f0
refactor: fix recs, cleanup
dkonieczek Feb 23, 2024
fa9c638
feat: badge component cleanup, add tests, storybook files, docs
dkonieczek Feb 28, 2024
3dac81e
docs: add last missing docs, fix failing test
dkonieczek Feb 29, 2024
1f7516b
chore: merge develop and resolve conflicts
dkonieczek Mar 6, 2024
0c028b1
chore: fix failing build and tests
dkonieczek Mar 6, 2024
c292db2
refactor: remove SearchBadgeStore from root stores
dkonieczek Mar 26, 2024
fe1dc82
chore: merge in develop
dkonieczek Mar 26, 2024
2d4b918
refactor: use new meta types, pairing refactor
dkonieczek Mar 28, 2024
4f30e6e
refactor: pr feedback: add MetaStore and SearchResultStore tests, pri…
dkonieczek Apr 3, 2024
6974a0e
refactor: remove css properties from MetaStore, cleanup
dkonieczek Apr 4, 2024
1316a97
chore: merge develop and rebuild package-lock
dkonieczek Apr 4, 2024
6ffb28b
feat: add BadgePill and BadgeRectangle components
dkonieczek Apr 17, 2024
26fdb4b
chore: add package-lock
dkonieczek Apr 17, 2024
3ba9fd9
fix(preact-components-badges): some small bugfixes to new badge compo…
chrisFrazier77 Apr 29, 2024
bb1842b
fix BadgeOverlay and BadgeCallout stories
dkonieczek Apr 30, 2024
c06ec17
fix: update badges to latest meta changes
dkonieczek May 6, 2024
f3accd2
refactor(badges): polish on badges to support stacked badges and grou…
korgon May 9, 2024
daf2e3c
Merge branch 'develop' into badges
korgon May 9, 2024
0541342
test: fixing tests after branch merger
korgon May 9, 2024
ec34389
refactor(preact-components/badges): adding 'renderEmpty' prop and fur…
korgon May 9, 2024
a53d718
refactor(store-mobx/storage): changing typing around StorageType enum…
korgon May 9, 2024
2689f9b
refactor(preact-demo): refactoring siteId switching and adding abilit…
korgon May 9, 2024
fc72bbc
fix(preact-components/overlaybadge): restoring lost positioning of th…
korgon May 9, 2024
8841830
test(store-mobx/storage): fixing test from previous enum refactor
korgon May 9, 2024
30b4f5a
fix: add right css property to OverlayBadge
dkonieczek May 13, 2024
9cc4a72
fix: remove getTag helper
dkonieczek May 13, 2024
9db11fb
fix: only lift badges if an object
dkonieczek May 13, 2024
c977223
fix: pr feedback
dkonieczek May 14, 2024
0daf2d8
fix: remove opacity from BadgePill and BadgeRectangle color default
dkonieczek May 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75,575 changes: 37,789 additions & 37,786 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion packages/snap-client/src/Client/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,15 @@ export class Client {
siteId: params.siteId || this.globals.siteId,
};

const [profile, recommendations] = await Promise.all([
const [meta, profile, recommendations] = await Promise.all([
this.meta(params.siteId ? { siteId: params.siteId } : undefined),
this.requesters.recommend.getProfile(profileParams),
this.requesters.recommend.batchRecommendations(recommendParams),
]);

return {
...profile,
meta,
results: recommendations[0].results,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('Network Cache', () => {
const cacheConfig = {
ttl: 1000,
enabled: true,
maxSize: 2, // KB
maxSize: 4, // KB
purgeable: true,
};

Expand Down Expand Up @@ -169,7 +169,7 @@ describe('Network Cache', () => {
const cacheConfig = {
ttl: 1000,
enabled: true,
maxSize: 2, // KB
maxSize: 4, // KB
purgeable: false,
};

Expand Down
10 changes: 8 additions & 2 deletions packages/snap-client/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { AppMode } from '@searchspring/snap-toolbox';
import type { MetaRequestModel, SearchResponseModelResult, SearchRequestModel, AutocompleteRequestModel } from '@searchspring/snapi-types';
import type {
MetaRequestModel,
SearchResponseModelResult,
SearchRequestModel,
AutocompleteRequestModel,
MetaResponseModel,
} from '@searchspring/snapi-types';

export type HTTPHeaders = { [key: string]: string };

Expand Down Expand Up @@ -193,4 +199,4 @@ type RecommendationRequestValueFilterModel = {
value: string | number;
};

export type RecommendCombinedResponseModel = ProfileResponseModel & { results: SearchResponseModelResult[] };
export type RecommendCombinedResponseModel = ProfileResponseModel & { results: SearchResponseModelResult[] } & { meta: MetaResponseModel };
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { h } from 'preact';

import { ArgsTable, PRIMARY_STORY } from '@storybook/addon-docs/blocks';

import { BadgeImageProps, BadgeImage } from './BadgeImage';
import { componentArgs } from '../../../utilities';
import Readme from '../BadgeImage/readme.md';

export default {
title: `Atoms/BadgeImage`,
component: BadgeImage,
parameters: {
docs: {
page: () => (
<div>
<Readme />
<ArgsTable story={PRIMARY_STORY} />
</div>
),
},
},
decorators: [
(Story: any) => (
<div
style={{
width: '200px',
height: '200px',
border: '2px dotted lightgrey',
}}
>
<Story />
</div>
),
],
argTypes: {
url: {
description: 'Badge image url',
type: { required: true },
table: {
type: {
summary: 'string',
},
defaultValue: { summary: '' },
},
control: { type: 'text' },
},
label: {
description: 'Badge image alt text',
table: {
type: {
summary: 'string',
},
defaultValue: { summary: '' },
},
control: { type: 'text' },
},
...componentArgs,
dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
},
};

export const Default = (args: BadgeImageProps) => <BadgeImage {...args} />;
Default.args = {
url: '//cdn.searchspring.net/ajax_search/img/star-badge-new-blue.png',
label: 'placeholder badge image',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { h } from 'preact';

import { render } from '@testing-library/preact';
import { ThemeProvider } from '../../../providers';

import { BadgeImage } from './BadgeImage';

const BADGE_URL = '/images/example.png';
const BADGE_LABEL = 'example badge';

describe('BadgeImage Component', () => {
it('renders BadgeImage with image src and alt text', () => {
const rendered = render(<BadgeImage url={BADGE_URL} label={BADGE_LABEL} />);
const BadgeImg = rendered.container.querySelector('.ss__badge-image');
expect(BadgeImg).toBeInTheDocument();
expect(BadgeImg).toHaveAttribute('src', BADGE_URL);
expect(BadgeImg).toHaveAttribute('alt', BADGE_LABEL);
});

dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
describe('BadgeImage theming works', () => {
dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
it('is themeable with ThemeProvider', () => {
const globalTheme = {
components: {
badgeImage: {
className: 'classy',
},
},
};
const rendered = render(
<ThemeProvider theme={globalTheme}>
<BadgeImage url={BADGE_URL} label={BADGE_LABEL} />
</ThemeProvider>
);
const element = rendered.container.querySelector('.ss__badge-image');
expect(element).toBeInTheDocument();
expect(element).toHaveClass(globalTheme.components.badgeImage.className);
});

it('is themeable with theme prop', () => {
const propTheme = {
components: {
badgeImage: {
className: 'classy',
},
},
};
const rendered = render(<BadgeImage url={BADGE_URL} label={BADGE_LABEL} theme={propTheme} />);
const element = rendered.container.querySelector('.ss__badge-image');
expect(element).toBeInTheDocument();
expect(element).toHaveClass(propTheme.components.badgeImage.className);
});

it('is theme prop overrides ThemeProvider', () => {
const globalTheme = {
components: {
badgeImage: {
className: 'classy',
label: 'oooo',
},
},
};
const propTheme = {
components: {
badgeImage: {
className: 'classier',
label: 'ahhhh',
},
},
};
const rendered = render(
<ThemeProvider theme={globalTheme}>
<BadgeImage url={BADGE_URL} label={BADGE_LABEL} theme={propTheme} />
</ThemeProvider>
);

const element = rendered.container.querySelector('.ss__badge-image');
expect(element).toBeInTheDocument();
expect(element).toHaveClass(propTheme.components.badgeImage.className);
expect(element).not.toHaveClass(globalTheme.components.badgeImage.className);
expect(element).toHaveAttribute('alt', propTheme.components.badgeImage.label);
expect(element).not.toHaveAttribute('alt', globalTheme.components.badgeImage.label);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/** @jsx jsx */
import { Fragment, h } from 'preact';

import { jsx, css } from '@emotion/react';
import classnames from 'classnames';
import { observer } from 'mobx-react-lite';

import { Theme, useTheme, CacheProvider } from '../../../providers';
import { ComponentProps, StylingCSS } from '../../../types';

const CSS = {
BadgeImage: () => {
return css({
maxHeight: '100%',
maxWidth: '100%',
});
},
};

export const BadgeImage = observer((properties: BadgeImageProps): JSX.Element => {
const globalTheme: Theme = useTheme();

const props: BadgeImageProps = {
// default props
// global theme
...globalTheme?.components?.badgeImage,
// props
...properties,
...properties.theme?.components?.badgeImage,
};
const { label, url, disableStyles, className, style } = props;

const styling: { css?: StylingCSS } = {};

if (!disableStyles) {
styling.css = [CSS.BadgeImage(), style];
} else if (style) {
styling.css = [style];
}

return url ? (
<CacheProvider>
<img {...styling} className={classnames('ss__badge-image', className)} alt={label} src={url} />
</CacheProvider>
) : (
<Fragment />
);
});

export interface BadgeImageProps extends ComponentProps {
url: string;
label?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './BadgeImage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# BadgeImage

Renders an image badge. It is expected to be used with `CalloutBadge` and `OverlayBadge` components.

## Usage

### url
The required `url` prop specifies the badge image `src` attribute.

```jsx
<BadgeImage src={'/images/example.png'} />
dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
```

dkonieczek marked this conversation as resolved.
Show resolved Hide resolved

### label
The `label` prop specifies the badge image `alt` attribute.

```jsx
<BadgeImage label={'example badge'} src={'/images/example.png'} />
dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { h } from 'preact';

import { ArgsTable, PRIMARY_STORY } from '@storybook/addon-docs/blocks';

import { BadgeTextProps, BadgeText } from './BadgeText';
import { componentArgs } from '../../../utilities';
import Readme from '../BadgeText/readme.md';

export default {
title: `Atoms/BadgeText`,
component: BadgeText,
parameters: {
docs: {
page: () => (
<div>
<Readme />
<ArgsTable story={PRIMARY_STORY} />
</div>
),
},
},
decorators: [
(Story: any) => (
<div
style={{
width: '200px',
height: '200px',
border: '2px dotted lightgrey',
}}
>
<Story />
</div>
),
],
argTypes: {
value: {
description: 'Badge text contents',
type: { required: true },
table: {
type: {
summary: 'string',
},
defaultValue: { summary: '' },
},
control: { type: 'text' },
},
dkonieczek marked this conversation as resolved.
Show resolved Hide resolved
color: {
description: 'Badge background color',
table: {
type: {
summary: 'string',
},
defaultValue: { summary: 'rgba(255, 255, 255, 0.5)' },
},
control: { type: 'color' },
},
colorText: {
description: 'Badge text color',
table: {
type: {
summary: 'string',
},
defaultValue: { summary: '#000000' },
},
control: { type: 'color' },
},
...componentArgs,
},
};

export const Default = (args: BadgeTextProps) => <BadgeText {...args} />;
Default.args = {
value: '30% Off',
color: '#0000FF',
colorText: '#FFFFFF',
};
Loading