Add legend to help users discover options
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
a03a151c42
commit
14c365b20f
|
@ -212,10 +212,22 @@ button {
|
|||
display: flex;
|
||||
font-size: .8rem;
|
||||
|
||||
> p {
|
||||
> .description {
|
||||
width: 50%;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
> .legend {
|
||||
//d-flex justify-content-end align-self-start
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
align-self: start;
|
||||
width: 50%;
|
||||
table {
|
||||
width: 75%;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.summary {
|
||||
|
@ -560,6 +572,7 @@ button {
|
|||
|
||||
.crate-bar {
|
||||
width: 100%;
|
||||
font-size: 0.9rem;
|
||||
|
||||
.crate-mode {
|
||||
text-align: left;
|
||||
|
@ -572,6 +585,7 @@ button {
|
|||
color: inherit;
|
||||
text-decoration: none;
|
||||
padding-bottom: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
a.active {
|
||||
font-weight: 700;
|
||||
|
@ -663,17 +677,13 @@ button {
|
|||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: .6rem;
|
||||
padding: .8rem 1rem;
|
||||
padding: .5rem .8rem;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15);
|
||||
text-align: left;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p + p {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.k-popup-connectors {
|
||||
|
|
|
@ -108,9 +108,17 @@
|
|||
}
|
||||
|
||||
#root-shop .panel .control > .description,
|
||||
#root-shop .panel .control > .legend,
|
||||
#root-shop .crate-mode {
|
||||
width: 100%;
|
||||
}
|
||||
#root-shop .panel .control > .legend {
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
}
|
||||
#root-shop .panel .control > .legend tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#root-shop .crate-mode {
|
||||
text-align: left;
|
||||
|
@ -308,12 +316,23 @@
|
|||
}
|
||||
|
||||
#root-shop .panel .control > .description,
|
||||
#root-shop .crate-mode {
|
||||
#root-shop .panel .control > .legend {
|
||||
width: 100%;
|
||||
}
|
||||
#root-shop .panel .control > .legend {
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
}
|
||||
#root-shop .panel .control > .legend tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#root-shop .crate-mode {
|
||||
#root-shop .panel .crate .crate-bar .crate-mode {
|
||||
text-align: left;
|
||||
width: 50%;
|
||||
}
|
||||
#root-shop .panel .crate .crate-bar .crate-mode a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary {
|
||||
|
@ -571,12 +590,23 @@
|
|||
}
|
||||
|
||||
#root-shop .panel .control > .description,
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
#root-shop .panel .control > .legend {
|
||||
width: 100%;
|
||||
}
|
||||
#root-shop .panel .control > .legend {
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
}
|
||||
#root-shop .panel .control > .legend tr {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#root-shop .panel .control > .crate-mode {
|
||||
#root-shop .panel .crate .crate-bar .crate-mode {
|
||||
text-align: left;
|
||||
width: 50%;
|
||||
}
|
||||
#root-shop .panel .crate .crate-bar .crate-mode a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#root-shop .panel .summary {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -26,10 +26,10 @@ export function Crate({crate_index}) {
|
|||
return (
|
||||
<div className="crate">
|
||||
|
||||
<div className="crate-bar d-inline-flex">
|
||||
<div className="crate-bar d-inline-flex justify-content-between">
|
||||
<CrateMode crate_index={crate_index}/>
|
||||
|
||||
<div className="delete-crate align-self-end align-content-end justify-content-end" onClick={() => onDeleteCrate(crate.id)}>
|
||||
<div className="delete-crate align-self-start align-content-start justify-content-end" onClick={() => onDeleteCrate(crate.id)}>
|
||||
Delete crate <img src="/images/shop/icon-remove.svg" alt="remove"/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@ export function CrateMode({crate_index}) {
|
|||
{modes_order.map((mode_name, _) => (
|
||||
<a
|
||||
key={mode_name}
|
||||
className={crate.crate_mode === mode_name ? 'active' : ''}
|
||||
className={(crate.crate_mode === mode_name ? 'active' : '') }
|
||||
onClick={() => setMode(crate.id, mode_name)}
|
||||
href="#"
|
||||
role="button">{crate_modes[mode_name].name}</a>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import React from "react";
|
||||
import {useShopStore} from "./shop_store";
|
||||
|
||||
export function LegendItem({icon, description}) {
|
||||
return (
|
||||
<tr>
|
||||
<td className="p-1"><img className="" width="20px" src={icon} alt={description}/></td>
|
||||
<td className="p-1"><span> {description} </span></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
export function Legend() {
|
||||
const legend = useShopStore(state => state.legend);
|
||||
|
||||
return <table>
|
||||
<tbody>
|
||||
{legend.map((item, i) => <LegendItem key={"legend_item"+i} icon={item.icon} description={item.description}/>)}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
|
@ -13,7 +13,7 @@ import {useRenderCount} from "@uidotdev/usehooks";
|
|||
* Component that renders all things for order.
|
||||
* It acts like-a layout, this component do nothing more.
|
||||
*/
|
||||
export function OrderPanel({title, description}) {
|
||||
export function OrderPanel({title, description, legend}) {
|
||||
// #!render_count
|
||||
const renderCount = useRenderCount();
|
||||
const isMobile = useShopStore((state) => state.isMobile);
|
||||
|
@ -26,8 +26,13 @@ export function OrderPanel({title, description}) {
|
|||
|
||||
<h2>{title}</h2>
|
||||
|
||||
<div className="control">
|
||||
<div className="control justify-content-between">
|
||||
{description}
|
||||
|
||||
<div className="legend">
|
||||
{legend}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -9,6 +9,7 @@ import {Layout} from "./Layout";
|
|||
import {Backlog} from "./Backlog";
|
||||
import {OrderPanel} from "./OrderPanel";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {Legend} from "./Legend";
|
||||
|
||||
/**
|
||||
* Component that renders the entire shop
|
||||
|
@ -59,6 +60,7 @@ export function Shop() {
|
|||
this ordering system, or if you need other configurations, email us directly anytime
|
||||
at <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>. The price is estimated and must
|
||||
be confirmed by a quote.</p>)}
|
||||
legend={(<Legend/>)}
|
||||
/>
|
||||
)}>
|
||||
</Layout>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
import {create} from "zustand";
|
||||
import {createWithEqualityFn} from "zustand/traditional";
|
||||
import {data as shared_data, itemsUnfoldedList} from "./utils";
|
||||
import {true_type_of} from "./options/utils";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
|
@ -28,6 +28,10 @@ const useBacklog = ((set, get) => ({
|
|||
cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element))
|
||||
}));
|
||||
|
||||
const useLegend = ((set, get) => ({
|
||||
legend: shared_data.legend
|
||||
}))
|
||||
|
||||
const useCrateModes = ((set, get) => ({
|
||||
crate_modes: shared_data.crateModes,
|
||||
modes_order: shared_data.crateModeOrder,
|
||||
|
@ -389,7 +393,7 @@ const useCart = ((set, get) => ({
|
|||
|
||||
setCrateMode: (id, mode) => {
|
||||
get()._setCrateMode(id, mode)
|
||||
get().fillExtData(crate_id);
|
||||
get().fillExtData(id);
|
||||
get().fillWarnings(id);
|
||||
get().setActiveCrate(id);
|
||||
},
|
||||
|
@ -435,7 +439,7 @@ const useCart = ((set, get) => ({
|
|||
}))
|
||||
|
||||
|
||||
export const useShopStore = create((...params) => ({
|
||||
export const useShopStore = createWithEqualityFn((...params) => ({
|
||||
...useBacklog(...params),
|
||||
...useCrateModes(...params),
|
||||
...useCart(...params),
|
||||
|
@ -443,4 +447,5 @@ export const useShopStore = create((...params) => ({
|
|||
...useLayout(...params),
|
||||
...useHighlighted(...params),
|
||||
...useImportJSON(...params),
|
||||
...useLegend(...params),
|
||||
}))
|
|
@ -3,6 +3,16 @@ const shop_data = {
|
|||
API_RFQ: 'https://hooks.m-labs.hk/rfq',
|
||||
currency: 'USD',
|
||||
|
||||
legend: [
|
||||
{icon: "/images/shop/icon-customize.svg", description: "cards configuration available"},
|
||||
{icon: "/images/shop/icon-add.svg", description: "add a card or crate to the order"},
|
||||
{icon: "/images/shop/icon-remove.svg", description: "remove a card or crate from the order"},
|
||||
{icon: "/images/shop/icon-clear.svg", description: "remove all the cards from the crate"},
|
||||
{icon: "/images/shop/icon-warning.svg", description: "the card or crate contains errors"},
|
||||
{icon: "/images/shop/icon-reminder.svg", description: "suggestions or hints available"},
|
||||
|
||||
],
|
||||
|
||||
crateModes: {
|
||||
rack: {
|
||||
id: 'rack',
|
||||
|
|
Loading…
Reference in New Issue