Skip to content

Commit

Permalink
feat: create SizeSelector component
Browse files Browse the repository at this point in the history
feat: add responsive

chore: changed imgs to template sting

fix: translation bug mobile

fix: add aria-checked event

feat: create new sizeSelector

feat: create methods and add navigation with keyboard

feat: finish component

fix: remove css noPet
  • Loading branch information
JonasGz committed Jul 2, 2024
1 parent 18e6b81 commit b7f79b7
Show file tree
Hide file tree
Showing 8 changed files with 422 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/components/SizeSelector/images/large.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/components/SizeSelector/images/medium.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/components/SizeSelector/images/small.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

164 changes: 164 additions & 0 deletions src/components/SizeSelector/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { Component } from 'pet-dex-utilities';
import small from './images/small';
import medium from './images/medium';
import large from './images/large';

import './index.scss';

const events = ['event'];

const html = `
<div class="container-size-selector" role="radiogroup">
<ul class="container-size-selector__size-list" data-select="sizelist">
<li class="container-size-selector__card" role="radio" aria-checked="false" tabindex="0">
<div class="container-size-selector__card-size">
<div class="container-size-selector__container-img">
${small}
</div>
<div class="container-size-selector__container-text">
<h3 class="container-size-selector__title">Small</h3>
<span class="container-size-selector__text">under 14kg</span>
</div>
</div>
</li>
<li class="container-size-selector__card container-size-selector__card--active" data-select="card-active" role="radio" aria-checked="true" tabindex="0">
<div class="container-size-selector__card-size">
<div class="container-size-selector__container-img">
${medium}
</div>
<div class="container-size-selector__container-text">
<h3 class="container-size-selector__title">Medium</h3>
<span class="container-size-selector__text">14-25kg</span>
</div>
</div>
</li>
<li class="container-size-selector__card" role="radio" aria-checked="false" tabindex="0">
<div class="container-size-selector__card-size">
<div class="container-size-selector__container-img">
${large}
</div>
<div class="container-size-selector__container-text">
<h3 class="container-size-selector__title">Large</h3>
<span class="container-size-selector__text">over 25kg</span>
</div>
</div>
</li>
</ul>
</div>
`;

export default function SizeSelector() {
Component.call(this, { html, events });

this.$sizeList = this.selected.get('sizelist');
this.$cards = Array.from(
this.$sizeList.querySelectorAll('.container-size-selector__card'),
);

const addEventListeners = (card, index) => {
card.addEventListener('click', () => {
this.selectCard(card, index);
this.getCardActiveEvent('click', card, index);
});

card.addEventListener('keydown', (key) => {
this.handleKeyDown(key, card);
});
};

this.$cards.forEach((card, index) => addEventListeners(card, index));
}

SizeSelector.prototype = Object.assign(
SizeSelector.prototype,
Component.prototype,
{
setText(index, title, subtitle) {
const h3 = this.$cards[index].querySelector('h3');
const span = this.$cards[index].querySelector('span');
h3.textContent = title;
span.textContent = subtitle;
},

handleKeyDown(event, card) {
let next;
let prev;
let nextIndex;
let prevIndex;
if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
next = card.nextElementSibling;
if (next) {
nextIndex = this.$cards.indexOf(next);
next.focus();
this.selectCard(next, nextIndex);
this.getCardActiveEvent('keydown', next, nextIndex);
}
}
if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
prev = card.previousElementSibling;
if (prev) {
prevIndex = this.$cards.indexOf(prev);
prev.focus();
this.selectCard(prev, prevIndex);
this.getCardActiveEvent('keydown', prev, prevIndex);
}
}
},

selectCard(selected, index) {
this.addActive(selected, 'container-size-selector__card--active');
this.centerCard(selected, index);
},

centerCard(card, index) {
if (index === 0)
this.$sizeList.classList.add(
'container-size-selector__size-list--active-padding',
);

const cardRect = card.getBoundingClientRect();
const listRect = this.$sizeList.getBoundingClientRect();
const cardCenter = cardRect.left + cardRect.width / 2;
const listCenter = listRect.left + listRect.width / 2;
const offset = cardCenter - listCenter;

this.$sizeList.scrollBy({
left: offset,
behavior: 'smooth',
});
},

addActive(element, className) {
this.$cards.forEach((card) => {
card.setAttribute('aria-checked', 'false');
card.classList.remove(className);
});
element.classList.add(className);
element.setAttribute('aria-checked', 'true');
},

getCardActiveEvent(eventName, card, index) {
if (eventName === 'click') {
this.emit('event', card, index);
}
if (eventName === 'keydown') {
this.emit('event', card, index);
}
},

getCardActive() {
const $activeCard = this.$cards.find((element) =>
element.classList.contains('container-size-selector__card--active'),
);
const indexCard = this.$cards.findIndex((element) =>
element.classList.contains('container-size-selector__card--active'),
);
return {
card: $activeCard,
index: indexCard,
};
},
},
);
190 changes: 190 additions & 0 deletions src/components/SizeSelector/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
@use '~styles/colors.scss' as colors;
@use '~styles/breakpoints.scss' as breakpoints;
@use '~styles/fonts.scss' as fonts;

.container-size-selector {
width: 100%;
max-width: 60rem;

display: flex;

&__size-list {
width: 100%;
overflow-x: hidden;

display: flex;
flex-direction: row;
gap: 1rem;

padding: 5rem 40% 5rem 0;

transition: padding 0.4s;

&--active-padding {
padding: 5rem 40%;
}
}

&__card:focus {
outline: none;
}

&__card {
display: flex;

align-items: center;
justify-content: center;

margin: 0 0.7rem;

padding: 1rem 0;

box-sizing: border-box;

background-color: colors.$secondary100;
box-shadow: 0 0 0.3rem 0.3rem colors.$gray150;
border-radius: 1.8rem;

transition: transform 0.3s;

&:focus {
outline: 0.3rem solid colors.$primary200;
}

&:hover {
outline: 0.3rem solid colors.$primary200;

.container-size-selector__svg path {
fill: colors.$primary200;
}

.container-size-selector__title {
color: colors.$primary200;
}

.container-size-selector__text {
color: colors.$primary200;
}

.container-size-selector__container-img {
background-color: rgb(209, 230, 255);
}
}

&--active {
transform: scale(1.3);
outline: 0.3rem solid colors.$primary200;

transition: transform 0.3s;

.container-size-selector__svg path {
fill: colors.$primary200;
}

.container-size-selector__title {
color: colors.$primary200;
font-size: fonts.$xs;
}

.container-size-selector__text {
color: colors.$primary200;
font-size: fonts.$xxs;
}

.container-size-selector__container-img {
width: 4.5rem;
height: 4.5rem;

background-color: rgb(209, 230, 255);
}
}
}

&__card-size {
width: 9.4rem;
height: 10.6rem;

display: flex;
flex-direction: column;
gap: 1.5rem;

align-items: center;
justify-content: center;
}

&__container-img {
width: 4rem;
height: 4rem;

display: flex;

align-items: center;

justify-content: center;

background-color: colors.$gray150;
border-radius: 100%;
}

&__container-text {
display: flex;
flex-direction: column;
gap: 0.3em;

align-items: center;

justify-content: center;
}

&__title {
font-family: fonts.$primaryFont;
color: colors.$gray800;
font-size: fonts.$xs;
font-weight: fonts.$semiBold;
}

&__text {
font-family: fonts.$primaryFont;
color: colors.$gray600;
font-size: fonts.$xxs;
font-weight: fonts.$regular;
}
}

@include breakpoints.from360 {
.container-size-selector {
&__size-list {
gap: 1.5rem;
}

&__card {
padding: 1rem 0;
}
}
}

@include breakpoints.from667 {
.container-size-selector {
&__size-list {
gap: 5rem;
}

&__card {
padding: 4rem 2rem;

&--active {
.container-size-selector__title {
font-size: fonts.$sm;
}

.container-size-selector__text {
font-size: fonts.$xs;
}
}
}

&__text {
font-size: fonts.$xs;
}
}
}
1 change: 1 addition & 0 deletions src/layouts/app/pages/NoPetRegirested/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
display: grid;

place-items: center;
justify-content: center;

&__description {
max-width: 33.5rem;
Expand Down
Loading

0 comments on commit b7f79b7

Please sign in to comment.