Minor visual fixes (#1927)

* Fix label

* Improve product organization widget labels

* Fix misaligned label

* Fix arrow behavior

* Add clickable rows to country picker

* Update snapshots

* Update messages

* Fix misaligned label

* Update snapshots
This commit is contained in:
Dominik Żegleń 2022-03-25 13:37:01 +01:00 committed by GitHub
parent 2b7d514da5
commit 1e77665b4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 3320 additions and 2256 deletions

View file

@ -430,7 +430,7 @@
"string": "Taxes"
},
"productTypeTaxesInputLabel": {
"string": "Taxes"
"string": "Tax group"
},
"productVariantCreatePricesSetPricePlaceholder": {
"context": "input label",
@ -6502,10 +6502,6 @@
"context": "modal button upload",
"string": "Upload"
},
"src_dot_products_dot_components_dot_ProductOrganization_dot_150865454": {
"context": "product is not configurable",
"string": "Simple"
},
"src_dot_products_dot_components_dot_ProductOrganization_dot_1755013298": {
"string": "Category"
},
@ -6517,7 +6513,6 @@
"string": "Organize Product"
},
"src_dot_products_dot_components_dot_ProductOrganization_dot_2754779425": {
"context": "product is configurable",
"string": "Configurable"
},
"src_dot_products_dot_components_dot_ProductOrganization_dot_2805838453": {

View file

@ -2,9 +2,9 @@ import { Popper, TextField, Typography } from "@material-ui/core";
import { fade } from "@material-ui/core/styles/colorManipulator";
import CloseIcon from "@material-ui/icons/Close";
import Debounce, { DebounceProps } from "@saleor/components/Debounce";
import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown";
import { IconButton, makeStyles } from "@saleor/macaw-ui";
import { ChevronIcon, IconButton, makeStyles } from "@saleor/macaw-ui";
import { FetchMoreProps } from "@saleor/types";
import classNames from "classnames";
import Downshift, { ControllerStateAndHelpers } from "downshift";
import { filter } from "fuzzaldrin";
import React from "react";
@ -65,12 +65,18 @@ const useStyles = makeStyles(
paddingRight: theme.spacing(1)
},
adornment: {
color: theme.palette.saleor.main[3],
cursor: "pointer",
userSelect: "none",
display: "flex",
alignItems: "center",
userSelect: "none",
cursor: "pointer",
"&:active": {
pointerEvents: "none"
"& svg": {
transition: theme.transitions.duration.shorter + "ms"
}
},
adornmentRotate: {
"& svg": {
transform: "rotate(180deg)"
}
}
}),
@ -167,7 +173,8 @@ const MultiAutocompleteSelectFieldComponent: React.FC<MultiAutocompleteSelectFie
toggleMenu,
getMenuProps,
highlightedIndex,
inputValue
inputValue,
getToggleButtonProps
}) => {
const displayCustomValue =
inputValue &&
@ -183,13 +190,17 @@ const MultiAutocompleteSelectFieldComponent: React.FC<MultiAutocompleteSelectFie
<TextField
InputProps={{
endAdornment: (
<div className={classes.adornment}>
<div
{...getToggleButtonProps()}
className={classNames(classes.adornment, {
[classes.adornmentRotate]: isOpen
})}
>
{endAdornment}
<ArrowDropdownIcon />
<ChevronIcon />
</div>
),
ref: anchor,
onBlur,
onFocus: () => {
if (fetchOnFocus) {
fetchChoices(inputValue);
@ -208,6 +219,7 @@ const MultiAutocompleteSelectFieldComponent: React.FC<MultiAutocompleteSelectFie
label={label}
fullWidth={true}
disabled={disabled}
onBlur={onBlur}
/>
{isOpen && (
<Popper

View file

@ -1,14 +1,13 @@
import { InputBase, Popper, TextField } from "@material-ui/core";
import { InputProps } from "@material-ui/core/Input";
import { ExtendedFormHelperTextProps } from "@saleor/channels/components/ChannelForm/types";
import { makeStyles } from "@saleor/macaw-ui";
import { ChevronIcon, makeStyles } from "@saleor/macaw-ui";
import { FetchMoreProps } from "@saleor/types";
import classNames from "classnames";
import Downshift from "downshift";
import { filter } from "fuzzaldrin";
import React from "react";
import ArrowDropdownIcon from "../../icons/ArrowDropdown";
import Debounce, { DebounceProps } from "../Debounce";
import SingleAutocompleteSelectFieldContent, {
SingleAutocompleteActionType,
@ -25,9 +24,16 @@ const useStyles = makeStyles(
padding: theme.spacing(2, 0)
},
adornment: {
color: theme.palette.saleor.main[3],
cursor: "pointer",
"&:active": {
pointerEvents: "none"
userSelect: "none",
"& svg": {
transition: theme.transitions.duration.shorter + "ms"
}
},
adornmentRotate: {
"& svg": {
transform: "rotate(180deg)"
}
}
}),
@ -128,7 +134,8 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
toggleMenu,
closeMenu,
highlightedIndex,
reset
reset,
getToggleButtonProps
}) => {
const isCustomValueSelected =
choices && selectedItem
@ -178,13 +185,17 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
const commonInputProps = {
...InputProps,
endAdornment: (
<div className={classes.adornment}>
<ArrowDropdownIcon />
<div
{...getToggleButtonProps()}
className={classNames(classes.adornment, {
[classes.adornmentRotate]: isOpen
})}
>
<ChevronIcon />
</div>
),
error,
id: undefined,
onBlur: handleBlur,
onFocus: () => {
if (fetchOnFocus) {
fetchChoices(inputValue);
@ -198,7 +209,8 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
"aria-label": "naked",
...commonInputProps,
autoFocus: true,
className: classes.nakedInput
className: classes.nakedInput,
onBlur: handleBlur
}
: {};
@ -215,7 +227,12 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
inputProps={{
...getInputProps({
placeholder,
onClick: !disabled && toggleMenu
onClick: () => {
if (disabled) {
return;
}
toggleMenu();
}
})
}}
error={error}

View file

@ -48,7 +48,7 @@ const ProductTypeTaxes: React.FC<ProductTypeTaxesProps> = props => {
disabled={disabled}
displayValue={taxTypeDisplayName}
label={intl.formatMessage({
defaultMessage: "Taxes",
defaultMessage: "Tax group",
id: "productTypeTaxesInputLabel"
})}
name={"taxType" as keyof ProductTypeForm}

View file

@ -12,6 +12,7 @@ import SingleAutocompleteSelectField, {
} from "@saleor/components/SingleAutocompleteSelectField";
import { ProductErrorFragment } from "@saleor/graphql";
import { ChangeEvent } from "@saleor/hooks/useForm";
import { commonMessages } from "@saleor/intl";
import { makeStyles } from "@saleor/macaw-ui";
import { maybe } from "@saleor/misc";
import { productTypeUrl } from "@saleor/productTypes/urls";
@ -132,28 +133,24 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
<Typography className={classes.label} variant="caption">
<FormattedMessage defaultMessage="Product Type" />
</Typography>
<Link
href={productTypeUrl(productType?.id) ?? ""}
disabled={!productType?.id}
>
{productType?.name ?? "..."}
</Link>
<Typography>
<Link
href={productTypeUrl(productType?.id) ?? ""}
disabled={!productType?.id}
>
{productType?.name ?? "..."}
</Link>
</Typography>
<CardSpacer />
<Typography className={classes.label} variant="caption">
<FormattedMessage defaultMessage="Product Type" />
<FormattedMessage defaultMessage="Configurable" />
</Typography>
<Typography>
{maybe(
() =>
productType.hasVariants
? intl.formatMessage({
defaultMessage: "Configurable",
description: "product is configurable"
})
: intl.formatMessage({
defaultMessage: "Simple",
description: "product is not configurable"
}),
? intl.formatMessage(commonMessages.yes)
: intl.formatMessage(commonMessages.no),
"..."
)}
</Typography>

View file

@ -38,7 +38,7 @@ const useExpanderStyles = makeStyles(
);
const useSummaryStyles = makeStyles(
theme => ({
() => ({
expanded: {},
root: {
width: "100%",
@ -46,10 +46,6 @@ const useSummaryStyles = makeStyles(
margin: 0,
padding: 0,
minHeight: 0,
paddingTop: theme.spacing(2),
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(5.5),
paddingBottom: theme.spacing(2),
"&$expanded": {
minHeight: 0
@ -66,6 +62,15 @@ const useSummaryStyles = makeStyles(
{ name: "VariantDetailsChannelsAvailabilityCardExpanderSummary" }
);
const useStyles = makeStyles(
() => ({
summaryContent: {
paddingTop: 0
}
}),
{ name: "VariantDetailsChannelsAvailabilityCard" }
);
interface VariantDetailsChannelsAvailabilityCardProps {
variant: ProductVariantFragment;
}
@ -73,6 +78,7 @@ interface VariantDetailsChannelsAvailabilityCardProps {
const VariantDetailsChannelsAvailabilityCard: React.FC<VariantDetailsChannelsAvailabilityCardProps> = ({
variant
}) => {
const classes = useStyles();
const expanderClasses = useExpanderStyles({});
const summaryClasses = useSummaryStyles({});
const localizeDate = useDateLocalize();
@ -139,18 +145,20 @@ const VariantDetailsChannelsAvailabilityCard: React.FC<VariantDetailsChannelsAva
return (
<CardContainer>
<Accordion classes={expanderClasses}>
<AccordionSummary
expandIcon={<IconChevronDown />}
classes={summaryClasses}
data-test-id="channels-variant-availability-summary"
>
<Typography variant="caption">
{intl.formatMessage(messages.subtitle, {
publishedInChannelsCount: publishedInChannelsListings.length,
availableChannelsCount: allAvailableChannelsListings.length
})}
</Typography>
</AccordionSummary>
<CardContent className={classes.summaryContent}>
<AccordionSummary
expandIcon={<IconChevronDown />}
classes={summaryClasses}
data-test-id="channels-variant-availability-summary"
>
<Typography variant="caption">
{intl.formatMessage(messages.subtitle, {
publishedInChannelsCount: publishedInChannelsListings.length,
availableChannelsCount: allAvailableChannelsListings.length
})}
</Typography>
</AccordionSummary>
</CardContent>
{channelListings.map(({ channel }) => (
<React.Fragment key={channel.id}>

View file

@ -28,16 +28,7 @@ import React from "react";
import { FormattedMessage, MessageDescriptor, useIntl } from "react-intl";
const useStyles = makeStyles(
theme => ({
caption: {
fontSize: 14,
padding: theme.spacing(0, 3, 2, 3)
},
colName: {
fontSize: 14,
paddingLeft: 0,
width: "auto"
},
() => ({
colPrice: {
textAlign: "right",
verticalAlign: "top",
@ -124,126 +115,125 @@ const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
description: "product pricing, section header"
})}
/>
<CardContent className={classes.pricingContent}>
<Typography variant="caption" className={classes.caption}>
<CardContent>
<Typography variant="body2">
{intl.formatMessage({
defaultMessage:
"Channels that dont have assigned prices will use their parent channel to define the price. Price will be converted to channels currency",
description: "info text"
})}
</Typography>
<ResponsiveTable className={classes.table}>
<TableHead>
<TableRow>
<TableCell>
<FormattedMessage
defaultMessage="Channel Name"
description="tabel column header"
/>
</TableCell>
<TableCell className={classes.colType}>
<FormattedMessage
defaultMessage="Selling Price"
description="tabel column header"
/>
</TableCell>
<TableCell className={classes.colType}>
<FormattedMessage
defaultMessage="Cost price"
description="tabel column header"
/>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{renderCollection(
ProductVariantChannelListings,
(listing, index) => {
const priceError = getFormChannelError(
formErrors.price,
listing.id
);
const costPriceError = getFormChannelError(
formErrors.costPrice,
listing.id
);
</CardContent>
<ResponsiveTable className={classes.table}>
<TableHead>
<TableRow>
<TableCell>
<FormattedMessage
defaultMessage="Channel Name"
description="tabel column header"
/>
</TableCell>
<TableCell className={classes.colType}>
<FormattedMessage
defaultMessage="Selling Price"
description="tabel column header"
/>
</TableCell>
<TableCell className={classes.colType}>
<FormattedMessage
defaultMessage="Cost price"
description="tabel column header"
/>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{renderCollection(
ProductVariantChannelListings,
(listing, index) => {
const priceError = getFormChannelError(
formErrors.price,
listing.id
);
const costPriceError = getFormChannelError(
formErrors.costPrice,
listing.id
);
return (
<TableRow key={listing?.id || `skeleton-${index}`}>
<TableCell>{listing?.name || <Skeleton />}</TableCell>
<TableCell className={classes.colPrice}>
{listing ? (
<PriceField
className={classes.input}
error={!!priceError}
label={intl.formatMessage({
defaultMessage: "Price"
})}
name={`${listing.id}-channel-price`}
value={listing.price || ""}
currencySymbol={listing.currency}
onChange={e =>
onChange(listing.id, {
costPrice: listing.costPrice,
price: e.target.value,
preorderThreshold: listing.preorderThreshold
})
}
disabled={loading}
required
hint={
priceError &&
getProductErrorMessage(priceError, intl)
}
/>
) : (
<Skeleton />
)}
</TableCell>
<TableCell className={classes.colPrice}>
{listing ? (
<PriceField
className={classes.input}
error={!!costPriceError}
label={intl.formatMessage({
defaultMessage: "Cost",
description: "tabel column header"
})}
name={`${listing.id}-channel-costPrice`}
value={listing.costPrice || ""}
currencySymbol={listing.currency}
onChange={e =>
onChange(listing.id, {
costPrice: e.target.value,
price: listing.price,
preorderThreshold: listing.preorderThreshold
})
}
disabled={loading}
hint={
costPriceError
? getProductErrorMessage(costPriceError, intl)
: ""
}
/>
) : (
<Skeleton />
)}
</TableCell>
</TableRow>
);
},
() => (
<TableRow>
<TableCell colSpan={numberOfColumns}>
<FormattedMessage defaultMessage="No channels found" />
return (
<TableRow key={listing?.id || `skeleton-${index}`}>
<TableCell>{listing?.name || <Skeleton />}</TableCell>
<TableCell className={classes.colPrice}>
{listing ? (
<PriceField
className={classes.input}
error={!!priceError}
label={intl.formatMessage({
defaultMessage: "Price"
})}
name={`${listing.id}-channel-price`}
value={listing.price || ""}
currencySymbol={listing.currency}
onChange={e =>
onChange(listing.id, {
costPrice: listing.costPrice,
price: e.target.value,
preorderThreshold: listing.preorderThreshold
})
}
disabled={loading}
required
hint={
priceError && getProductErrorMessage(priceError, intl)
}
/>
) : (
<Skeleton />
)}
</TableCell>
<TableCell className={classes.colPrice}>
{listing ? (
<PriceField
className={classes.input}
error={!!costPriceError}
label={intl.formatMessage({
defaultMessage: "Cost",
description: "tabel column header"
})}
name={`${listing.id}-channel-costPrice`}
value={listing.costPrice || ""}
currencySymbol={listing.currency}
onChange={e =>
onChange(listing.id, {
costPrice: e.target.value,
price: listing.price,
preorderThreshold: listing.preorderThreshold
})
}
disabled={loading}
hint={
costPriceError
? getProductErrorMessage(costPriceError, intl)
: ""
}
/>
) : (
<Skeleton />
)}
</TableCell>
</TableRow>
)
)}
</TableBody>
</ResponsiveTable>
</CardContent>
);
},
() => (
<TableRow>
<TableCell colSpan={numberOfColumns}>
<FormattedMessage defaultMessage="No channels found" />
</TableCell>
</TableRow>
)
)}
</TableBody>
</ResponsiveTable>
</Card>
);
};

View file

@ -127,7 +127,14 @@ const ShippingZoneCountriesAssignDialog: React.FC<ShippingZoneCountriesAssignDia
<FormSpacer />
<ResponsiveTable className={classes.table}>
<TableBody>
<TableRow>
<TableRow
className={classes.clickableRow}
onClick={() =>
handleRestOfTheWorldChange(
!isRestOfTheWorldSelected
)
}
>
<TableCell className={classes.wideCell}>
<FormattedMessage
{...messages.restOfTheWorldCheckbox}
@ -145,11 +152,6 @@ const ShippingZoneCountriesAssignDialog: React.FC<ShippingZoneCountriesAssignDia
<Checkbox
name="restOfTheWorld"
checked={isRestOfTheWorldSelected}
onChange={() =>
handleRestOfTheWorldChange(
!isRestOfTheWorldSelected
)
}
/>
</TableCell>
</TableRow>
@ -171,7 +173,13 @@ const ShippingZoneCountriesAssignDialog: React.FC<ShippingZoneCountriesAssignDia
const isChecked = countrySelectionMap[country.code];
return (
<TableRow key={country.code}>
<TableRow
className={classes.clickableRow}
onClick={() =>
handleCountryChange(country.code, !isChecked)
}
key={country.code}
>
<TableCell className={classes.wideCell}>
{country.country}
</TableCell>
@ -179,12 +187,7 @@ const ShippingZoneCountriesAssignDialog: React.FC<ShippingZoneCountriesAssignDia
padding="checkbox"
className={classes.checkboxCell}
>
<Checkbox
checked={isChecked}
onChange={() =>
handleCountryChange(country.code, !isChecked)
}
/>
<Checkbox checked={isChecked} />
</TableCell>
</TableRow>
);

View file

@ -2,6 +2,10 @@ import { makeStyles } from "@saleor/macaw-ui";
export const useStyles = makeStyles(
theme => ({
clickableRow: {
cursor: "pointer",
userSelect: "none"
},
checkboxCell: {
paddingLeft: 0
},

File diff suppressed because it is too large Load diff