mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-27 19:42:11 +10:00
Merge pull request #663 from sharetribe/show-multi-value
Add a component for presenting multi value data
This commit is contained in:
commit
2b4d56eb7d
6 changed files with 211 additions and 0 deletions
|
|
@ -1,3 +1,12 @@
|
|||
/*
|
||||
* Renders a group of checkboxes that can be used to select
|
||||
* multiple values from a set of options.
|
||||
*
|
||||
* The corresponding component when rendering the selected
|
||||
* values is PropertyGroup.
|
||||
*
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
|
|
|||
84
src/components/PropertyGroup/PropertyGroup.css
Normal file
84
src/components/PropertyGroup/PropertyGroup.css
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
:root {
|
||||
--lineHeight: 24px;
|
||||
--lineThroughTop: calc(var(--lineHeight) - 7px);
|
||||
--lineThroughBottom: calc(var(--lineHeight) - 6px);
|
||||
--lineHeightMobile: 20px;
|
||||
--lineThroughTopMobile: calc(var(--lineHeightMobile) - 5px);
|
||||
--lineThroughBottomMobile: calc(var(--lineHeightMobile) - 4px);
|
||||
}
|
||||
|
||||
.root {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.twoColumns {
|
||||
@media (--viewportMedium) {
|
||||
column-count: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.checkIcon {
|
||||
margin: 1px 8px -1px 0;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.marketplaceFill {
|
||||
fill: var(--marketplaceColor);
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.textWrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.selectedText,
|
||||
.notSelectedText {
|
||||
@apply --marketplaceBodyFontStyles;
|
||||
line-height: var(--lineHeight);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.selectedText {
|
||||
font-weight: var(--fontWeightSemiBold);
|
||||
}
|
||||
|
||||
.notSelectedText {
|
||||
color: var(--matterColorNegative);
|
||||
position: relative;
|
||||
|
||||
/* line-through */
|
||||
background-image: linear-gradient(
|
||||
transparent var(--lineThroughTopMobile),
|
||||
var(--matterColorNegative) var(--lineThroughTopMobile),
|
||||
var(--matterColorNegative) var(--lineThroughBottomMobile),
|
||||
transparent var(--lineThroughBottomMobile)
|
||||
);
|
||||
|
||||
@media (--viewportMedium) {
|
||||
background-image: linear-gradient(
|
||||
transparent var(--lineThroughTop),
|
||||
var(--matterColorNegative) var(--lineThroughTop),
|
||||
var(--matterColorNegative) var(--lineThroughBottom),
|
||||
transparent var(--lineThroughBottom)
|
||||
);
|
||||
}
|
||||
}
|
||||
23
src/components/PropertyGroup/PropertyGroup.example.js
Normal file
23
src/components/PropertyGroup/PropertyGroup.example.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import PropertyGroup from './PropertyGroup';
|
||||
|
||||
const exampleOptions = [
|
||||
{ value: 'towels', text: 'Towels' },
|
||||
{ value: 'bathroom', text: 'Bathroom' },
|
||||
{ value: 'swimming', text: 'Swimming' },
|
||||
{ value: 'own_drinks_allowed', text: 'Own drinks allowed' },
|
||||
{ value: 'jacuzzi', text: 'Jacuzzi' },
|
||||
{ value: 'audiovisual_entertainment', text: 'Audiovisual entertainment' },
|
||||
{ value: 'barbeque', text: 'Barbeque' },
|
||||
{ value: 'own_food_allowed', text: 'Own food allowed' },
|
||||
];
|
||||
|
||||
export const WithSomeSelected = {
|
||||
component: PropertyGroup,
|
||||
props: {
|
||||
id: 'amenities',
|
||||
options: exampleOptions,
|
||||
selectedOptions: ['towels', 'bathroom', 'barbeque'],
|
||||
twoColumns: true,
|
||||
},
|
||||
group: 'misc',
|
||||
};
|
||||
92
src/components/PropertyGroup/PropertyGroup.js
Normal file
92
src/components/PropertyGroup/PropertyGroup.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Renders a set of options with selected and non-selected values.
|
||||
*
|
||||
* The corresponding component when selecting the values is
|
||||
* FieldGroupCheckbox.
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { includes } from 'lodash';
|
||||
|
||||
import css from './PropertyGroup.css';
|
||||
|
||||
const checkSelected = (options, selectedOptions) => {
|
||||
return options.map(option => ({
|
||||
text: option.text,
|
||||
value: option.value,
|
||||
isSelected: includes(selectedOptions, option.value),
|
||||
}));
|
||||
};
|
||||
|
||||
const IconCheck = props => {
|
||||
const isVisible = props.isVisible;
|
||||
const classes = isVisible ? css.checkIcon : classNames(css.checkIcon, css.hidden);
|
||||
|
||||
return (
|
||||
<svg width="9" height="9" xmlns="http://www.w3.org/2000/svg" className={classes}>
|
||||
<path
|
||||
className={css.marketplaceFill}
|
||||
d="M2.636621 7.7824771L.3573694 5.6447948c-.4764924-.4739011-.4764924-1.2418639 0-1.7181952.4777142-.473901 1.251098-.473901 1.7288122 0l1.260291 1.1254783L6.1721653.505847C6.565577-.0373166 7.326743-.1636902 7.8777637.227582c.5473554.3912721.6731983 1.150729.2797866 1.6951076L4.4924979 7.631801c-.2199195.306213-.5803433.5067096-.9920816.5067096-.3225487 0-.6328797-.1263736-.8637952-.3560334z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const Item = props => {
|
||||
const { text, isSelected } = props;
|
||||
const textClass = isSelected ? css.selectedText : css.notSelectedText;
|
||||
return (
|
||||
<li className={css.item}>
|
||||
<div className={css.iconWrapper}>
|
||||
<IconCheck isVisible={isSelected} />
|
||||
</div>
|
||||
<div className={css.textWrapper}>
|
||||
<span className={textClass}>{text}</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const PropertyGroup = props => {
|
||||
const { rootClassName, className, id, options, selectedOptions, twoColumns } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const listClasses = twoColumns ? classNames(classes, css.twoColumns) : classes;
|
||||
|
||||
const checked = checkSelected(options, selectedOptions);
|
||||
|
||||
return (
|
||||
<ul className={listClasses}>
|
||||
{checked.map(option => (
|
||||
<Item key={`${id}.${option.value}`} text={option.text} isSelected={option.isSelected} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
PropertyGroup.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
twoColumns: false,
|
||||
};
|
||||
|
||||
const { arrayOf, bool, node, shape, string } = PropTypes;
|
||||
|
||||
PropertyGroup.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
id: string.isRequired,
|
||||
options: arrayOf(
|
||||
shape({
|
||||
value: string.isRequired,
|
||||
text: node.isRequired,
|
||||
})
|
||||
),
|
||||
selectedOptions: arrayOf(string).isRequired,
|
||||
twoColumns: bool,
|
||||
};
|
||||
|
||||
export default PropertyGroup;
|
||||
|
|
@ -86,6 +86,7 @@ export { default as Page } from './Page/Page';
|
|||
export { default as PaginationLinks } from './PaginationLinks/PaginationLinks';
|
||||
export { default as PrivacyPolicy } from './PrivacyPolicy/PrivacyPolicy';
|
||||
export { default as Promised } from './Promised/Promised';
|
||||
export { default as PropertyGroup } from './PropertyGroup/PropertyGroup';
|
||||
export { default as ResponsiveImage } from './ResponsiveImage/ResponsiveImage';
|
||||
export { default as ReviewModal } from './ReviewModal/ReviewModal';
|
||||
export { default as ReviewRating } from './ReviewRating/ReviewRating';
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import * as Modal from './components/Modal/Modal.example';
|
|||
import * as ModalInMobile from './components/ModalInMobile/ModalInMobile.example';
|
||||
import * as NamedLink from './components/NamedLink/NamedLink.example';
|
||||
import * as PaginationLinks from './components/PaginationLinks/PaginationLinks.example';
|
||||
import * as PropertyGroup from './components/PropertyGroup/PropertyGroup.example';
|
||||
import * as ResponsiveImage from './components/ResponsiveImage/ResponsiveImage.example';
|
||||
import * as ReviewRating from './components/ReviewRating/ReviewRating.example';
|
||||
import * as Reviews from './components/Reviews/Reviews.example';
|
||||
|
|
@ -122,6 +123,7 @@ export {
|
|||
PasswordRecoveryForm,
|
||||
PasswordResetForm,
|
||||
PayoutDetailsForm,
|
||||
PropertyGroup,
|
||||
ResponsiveImage,
|
||||
ReviewForm,
|
||||
ReviewRating,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue