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

YSHOP2-1133: Add ResourcePicker component #184

Merged
merged 31 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cffa0b1
dark: improve checkbox styles
eihabkhan1 Dec 12, 2023
b6e8668
add initial ResourcePicker's Resource component
eihabkhan1 Dec 12, 2023
61fa783
add display functionality
eihabkhan1 Dec 12, 2023
064586a
bump vue from 3.2.45 to 3.3.0 to add support for types import
eihabkhan1 Dec 13, 2023
7ac155a
add emits and v-models
eihabkhan1 Dec 13, 2023
2e1e057
made an oopsie in Modal.vue
eihabkhan1 Dec 13, 2023
3a6d1df
add selectedResources model
eihabkhan1 Dec 13, 2023
2742acd
update checkbox to include indeterminate state
eihabkhan1 Dec 13, 2023
41ce174
adding support for variants (wip)
eihabkhan1 Dec 13, 2023
b40c95a
Merge branch 'main' into YSHOP2-1133
eihabkhan1 Dec 14, 2023
5377dee
add enter event to search bar
eihabkhan1 Dec 14, 2023
c97c8fb
add loading state to picker
eihabkhan1 Dec 14, 2023
19f92e9
remove unnecessary emits
eihabkhan1 Dec 14, 2023
753211b
minor bug fix
eihabkhan1 Dec 14, 2023
12cfa8d
code cleanups
eihabkhan1 Dec 14, 2023
636e008
add empty state
eihabkhan1 Dec 14, 2023
6b461d9
code refactor
eihabkhan1 Dec 14, 2023
f849518
improve how variants are displayed
eihabkhan1 Dec 14, 2023
3615d45
refactor checkbox logic
eihabkhan1 Dec 15, 2023
524f0ae
add finalize ResourcePicker 🎉
eihabkhan1 Dec 15, 2023
a7c5a43
minor cleanups
eihabkhan1 Dec 15, 2023
a498e5c
minor code cleanup
eihabkhan1 Dec 18, 2023
693e438
more cleanups
eihabkhan1 Dec 18, 2023
e6d58da
minor bug fixes
eihabkhan1 Dec 18, 2023
4ebe954
code cleanups
eihabkhan1 Dec 18, 2023
04090ae
Merge branch 'main' into YSHOP2-1133
eihabkhan1 Dec 18, 2023
5812f5d
Merge branch 'main' into YSHOP2-1133
eihabkhan1 Dec 25, 2023
141c3c0
fix broken pnpm-lock
eihabkhan1 Dec 25, 2023
c49f2c1
code cleanup
eihabkhan1 Dec 25, 2023
644a576
fixing selection bug
eihabkhan1 Dec 25, 2023
607688a
minor selection bug fix
eihabkhan1 Dec 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/vue3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"typescript": "4.8.2",
"unocss": "^0.47.6",
"vite": "^4.0.3",
"vue": "^3.2.45",
"vue": "^3.3.0",
"vue-tsc": "1.0.9"
}
}
134 changes: 122 additions & 12 deletions packages/vue3/src/_dev/App.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,134 @@
<script setup lang="ts">
import 'uno.css';
import '../assets/main.css';
import { Alert } from '~/components';
import '~/assets/main.css';
import { ref } from 'vue';
import { PrimaryButton, ResourcePicker } from '~/components';
import type { Resource } from '~/components/ResourcePicker/types';
const MOCK_RESOURCES: Resource[] = [
{
id: 1,
thumbnailUrl: '',
name: 'Apple MacBook Pro',
price: '$10.99',
stock: 99,
isChecked: false,
variants: [
{
id: 33,
thumbnailUrl: '',
name: 'Apple MacBook Pro 16 M3 Max',
price: '$10.99',
stock: 99,
isChecked: false,
},
{
id: 21,
thumbnailUrl: '',
name: 'Apple MacBook Pro 14 M3 Pro',
price: '$10.99',
stock: 99,
isChecked: false,
},
],
},
{
id: 2,
thumbnailUrl: '',
name: 'Apple iMac',
price: '$10.99',
stock: 99,
isChecked: false,
},
{
id: 3,
thumbnailUrl: '',
name: 'Apple Watch',
price: '$10.99',
stock: 99,
isChecked: false,
},
];
const showPicker = ref(false);
const showLoadingPicker = ref(false);
const showEmptyPicker = ref(false);
const selectedResources = ref<Resource[]>([]);
const onConfirm = (resources: Resource[]) => {
selectedResources.value = resources;
showPicker.value = false;
};
const onSearch = (term: string) => {
console.log('Search term:', term);
};
</script>

<template>
<div class="container">
<Alert type="error">
<template #title>
Profile Updated
</template>
<template #description>
Your profile information has been successfully updated.
</template>
</Alert>
<div class="picker">
<ResourcePicker
v-model:visible="showPicker"
:resources="MOCK_RESOURCES"
stock-label="in stock"
:is-loading="false"
@confirm="onConfirm"
@search="onSearch"
/>
<PrimaryButton @click="showPicker = true;">
<span>Open Picker</span>
</PrimaryButton>
</div>
<div class="picker">
<ResourcePicker
v-model:visible="showLoadingPicker"
:is-loading="true"
/>
<PrimaryButton @click="showLoadingPicker = true;">
<span>Open Loading Picker</span>
</PrimaryButton>
</div>
<div class="picker">
<ResourcePicker
v-model:visible="showEmptyPicker"
:resources="[]"
:is-loading="false"
/>
<PrimaryButton @click="showEmptyPicker = true;">
<span>Open Empty Picker</span>
</PrimaryButton>
</div>
<div class="selection-container">
<p>Selected Resources:</p>
<pre>{{ selectedResources }}</pre>
</div>
</div>
</template>

<style scoped>
div {
margin: 10px;
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100vw;
min-height: 100vh;
margin: 0 auto;
padding: 32px 0;
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
font-family: "Mona Sans";
gap: 32px;
}
.selection-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 400px;
padding: 32px;
border: 1px solid var(--gray-200);
border-radius: 8px;
}
</style>
4 changes: 3 additions & 1 deletion packages/vue3/src/components/Checkbox/Checkbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const idAttr = Utils.uid('checkbox');
<label :for="idAttr" v-bind="$attrs">
<div class="checkbox" :class="{ 'has-label': slots.label }">
<input v-bind="$attrs" :id="idAttr" v-model="model" type="checkbox" class="input" :value="value">
<span class="checkmark" :class="{ checked }"> <i class="i-youcan-check" /> </span>
<span v-if="!$attrs.indeterminate" class="checkmark" :class="{ checked }"> <i class="i-youcan-check" /> </span>
<span v-else class="checkmark" :class="[{ checked }]"> <i class="i-youcan-minus" /> </span>
</div>
<div v-if="slots.label" class="label">
<slot name="label" />
Expand All @@ -44,6 +45,7 @@ label {
.label {
display: inline-block;
flex: 1;
font: var(--text-sm-regular);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<script setup lang="ts">
import { computed } from 'vue';
import { Checkbox, Thumbnail } from '~/components';
import type { ResourceProps } from '~/components/ResourcePicker/types';
const props = withDefaults(defineProps<ResourceProps>(), {
stockLabel: 'Stock',
name: 'Name',
showStock: false,
showThumbnail: true,
});
const emit = defineEmits(['change', 'update:model-value']);
const model = computed({
get: () => props.modelValue,
set: (value: boolean) => emit('update:model-value', value),
});
function handleCheck(e: Event) {
emit('change', e, props.resource);
}
</script>

<template>
<Checkbox v-model="model" class="container" :class="!showThumbnail && 'variant'" :indeterminate="indeterminate" @change.stop="handleCheck">
<template #label>
<div class="content">
<div class="info">
<Thumbnail v-if="showThumbnail" :src="resource.thumbnailUrl" />
<p class="name">
{{ resource.name }}
</p>
</div>
<div class="inventory-price">
<span v-if="showStock" class="stock">{{ resource.stock }} {{ stockLabel }}</span>
<p class="price">
{{ resource.price }}
</p>
</div>
</div>
</template>
</Checkbox>
</template>

<style scoped>
.container {
display: flex;
justify-content: start;
padding: 0 16px;
transition: background-color 0.3s;
border-bottom: var(--border);
cursor: pointer;
gap: 8px;
}
.container:hover {
background-color: var(--gray-50);
}
.variant {
padding-inline-start: 52px;
}
.content {
display: flex;
flex: 1 1 auto;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.info {
display: flex;
flex-basis: 55%;
align-items: center;
gap: 8px;
}
.info .thumbnail {
margin: 16px 0;
}
.inventory-price {
display: flex;
flex-basis: 45%;
align-items: center;
gap: 16px;
justify-content: end;
}
.inventory-price .stock {
color: var(--gray-400);
}
</style>