Skip to content

Commit

Permalink
feat: Implementing Rating component (#139)
Browse files Browse the repository at this point in the history
* feat: Implementing Rating component

Co-authored-by: Simeon Simeonoff <[email protected]>
Co-authored-by: MPopov <[email protected]>
Co-authored-by: Stamen Stoychev <[email protected]>
Co-authored-by: Diyan Dimitrov <[email protected]>
Co-authored-by: Diyan Dimitrov <[email protected]>
  • Loading branch information
6 people authored Mar 15, 2022
1 parent 9c396a2 commit af4c67e
Show file tree
Hide file tree
Showing 15 changed files with 1,184 additions and 7 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- Linear Progress component
- Circular Progress component
- Chip Component
- Snackbar Component
- Toast Component
- Chip component
- Snackbar component
- Toast component
- Rating component
- Component themes can be changed at runtime by calling the `configureTheme(theme: Theme)` function

## [2.0.0] - 2022-02-03
Expand Down
5 changes: 3 additions & 2 deletions scripts/build-stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function extractTags(meta) {
.map((prop) => {
const options =
UNION_TYPE_REGEX.test(prop.type) &&

!SUPPORTED_TYPES.some(
(type) => prop.type === type || prop.type.startsWith(`${type} `)
)
Expand All @@ -98,8 +99,8 @@ function extractTags(meta) {
? prop.type === 'boolean'
? prop.default === 'true'
: prop.type === 'Date'
? undefined
: prop.default.replace(/"/g, '')
? undefined
: prop.default.replace(/"/g, '')
: undefined,
},
];
Expand Down
4 changes: 4 additions & 0 deletions src/components/common/definitions/defineAllComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import IgcNavDrawerItemComponent from '../../nav-drawer/nav-drawer-item';
import IgcNavbarComponent from '../../navbar/navbar';
import IgcRadioGroupComponent from '../../radio-group/radio-group';
import IgcRadioComponent from '../../radio/radio';
import IgcRatingComponent from '../../rating/rating';
import IgcRatingSymbolComponent from '../../rating/rating-symbol';
import IgcRippleComponent from '../../ripple/ripple';
import IgcRangeSliderComponent from '../../slider/range-slider';
import IgcSliderComponent from '../../slider/slider';
Expand Down Expand Up @@ -60,6 +62,8 @@ const allComponents: CustomElementConstructor[] = [
IgcNavbarComponent,
IgcRadioComponent,
IgcRadioGroupComponent,
IgcRatingComponent,
IgcRatingSymbolComponent,
IgcRippleComponent,
IgcSliderComponent,
IgcToastComponent,
Expand Down
6 changes: 6 additions & 0 deletions src/components/form/form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
defineAllComponents,
IgcFormComponent,
IgcRadioComponent,
IgcRatingComponent,
} from '../../index.js';

describe('Form', () => {
Expand Down Expand Up @@ -87,6 +88,7 @@ describe('Form', () => {
const expectedValues = new Map<string, any>();
expectedValues.set('textarea', 'textareaValue');
expectedValues.set('inputText', 'inputTextValue');
expectedValues.set('igcRating', '3');
let formData = el.getFormData();
verifyFormDataValues(formData, expectedValues);

Expand Down Expand Up @@ -120,13 +122,16 @@ describe('Form', () => {
inputCheckbox.checked = true;
const igcRadio = el.querySelector('igc-radio') as IgcRadioComponent;
igcRadio.checked = true;
const rating = el.querySelector('igc-rating') as IgcRatingComponent;
rating.value = 5;
await elementUpdated(el);
el.reset();
await elementUpdated(el);

const expectedValues = new Map<string, any>();
expectedValues.set('textarea', 'textareaValue');
expectedValues.set('inputText', 'inputTextValue');
expectedValues.set('igcRating', '3');
const formData = el.getFormData();
verifyFormDataValues(formData, expectedValues);
});
Expand Down Expand Up @@ -170,6 +175,7 @@ describe('Form', () => {
<input type="checkbox" name="inputCheckbox" value="inputCheckboxValue">
<igc-radio name="igcRadio" value="igcRadioValue"></igc-radio>
<igc-button type="submit">Submit</igc-button>
<igc-rating name="igcRating" value="3"></igc-rating>
</igc-form>
`
) => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/form/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default class IgcFormComponent extends EventEmitterMixin<
'igc-switch',
'igc-checkbox',
];
private _controlsWithValue = ['input', 'igc-input', 'textarea'];
private _controlsWithValue = ['input', 'igc-input', 'textarea', 'igc-rating'];
private _controlsThatSubmit = [
'input',
'button',
Expand Down Expand Up @@ -85,7 +85,7 @@ export default class IgcFormComponent extends EventEmitterMixin<
(tagName !== 'input' && this._controlsWithChecked.includes(tagName))
) {
element.checked = element.hasAttribute('checked');
} else if (tagName === 'igc-input') {
} else if (tagName === 'igc-input' || tagName === 'igc-rating') {
element.value = element.getAttribute('value');
} else if (this._controlsWithValue.includes(tagName)) {
element.value = element.defaultValue;
Expand Down
23 changes: 23 additions & 0 deletions src/components/rating/rating-symbol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { LitElement } from 'lit';

/**
*
* Used when a custom icon/symbol/element needs to be passed to the igc-rating component.
*
* @element igc-rating-symbol
*
* @slot - Default slot for projected symbols/icons.
*/
export default class IgcRatingSymbolComponent extends LitElement {
public static readonly tagName = 'igc-rating-symbol';

protected override createRenderRoot() {
return this;
}
}

declare global {
interface HTMLElementTagNameMap {
'igc-rating-symbol': IgcRatingSymbolComponent;
}
}
177 changes: 177 additions & 0 deletions src/components/rating/rating.base.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
@use '../../styles/common/component';
@use '../../styles/utilities' as *;

$size-small: rem(16px);
$size-medium: rem(20px);
$size-large: rem(24px);
$spacing: rem(2px);
$color-label: color(gray, 700) !default;
$color-symbols: color(gray, 900) !default;
$selected-color: color(primary) !default;
$disabled-color: color(gray, 400) !default;
$disabled-selected-color: color(gray, 600) !default;

:host {
display: inline-flex;
font-family: var(--igc-font-family);
align-items: flex-start;
flex-direction: column;
gap: $spacing * 2;
}

%fraction {
position: absolute;
overflow: hidden;
inset-inline-start: 0;
min-width: 0 !important;
z-index: 1;
}

slot {
display: none;
}

[part='base'] {
position: relative;
display: inline-flex;
user-select: none;
}

[part~='label'] {
@include type-category('caption');

color: $color-label;
padding-inline-start: $spacing;
}

[part~='symbols-wrapper'] {
color: $color-symbols;
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: $spacing;
gap: $spacing;
counter-reset: symbols;
inset-inline-start: 0;
}

[part~='fraction'] {
@extend %fraction;

[part='symbols-wrapper'] {
@extend %fraction;

color: $selected-color;

[part~='symbol'] {
filter: grayscale(0);
}
}
}

[part~='symbol'] {
color: inherit;
font-size: 100%;
display: flex;
align-items: center;
justify-content: center;
filter: grayscale(100%);
cursor: pointer;

igc-icon {
color: inherit;
}

&:empty {
&::before {
content: counter(symbols);
counter-increment: symbols;
}
}
}

:host([disabled]) {
pointer-events: none;

[part~='label'] {
color: $disabled-color !important;
}

[part~='symbols-wrapper'] {
color: $disabled-color;
}

[part~='fraction'] {
[part='symbols-wrapper'] {
color: $disabled-selected-color;
filter: grayscale(50%);
}
}
}

[part~='large'] {
min-width: $size-large;
min-height: $size-large;
line-height: $size-large;
width: $size-large;
height: $size-large;

igc-icon {
width: $size-large;
height: $size-large;
font-size: $size-large;
}
}

[part~='medium'] {
min-width: $size-medium;
min-height: $size-medium;
line-height: $size-medium;
width: $size-medium;
height: $size-medium;

igc-icon {
width: $size-medium;
height: $size-medium;
font-size: $size-medium;
}
}

[part~='small'] {
min-width: $size-small;
min-height: $size-small;
line-height: $size-small;
width: $size-small;
height: $size-small;

igc-icon {
width: $size-small;
height: $size-small;
font-size: $size-small;
}
}

[part='label large'],
[part='label medium'],
[part='label small'] {
height: auto;
width: auto;
min-height: 0;
min-width: 0;
}

[part='fraction large'] {
min-height: calc(#{$size-large} + (#{$spacing} * 2));
height: calc(#{$size-large} + (#{$spacing} * 2));
}

[part='fraction medium'] {
min-height: calc(#{$size-medium} + (#{$spacing} * 2));
height: calc(#{$size-medium} + (#{$spacing} * 2));
}

[part='fraction small'] {
min-height: calc(#{$size-small} + (#{$spacing} * 2));
height: calc(#{$size-small} + (#{$spacing} * 2));
}
10 changes: 10 additions & 0 deletions src/components/rating/rating.bootstrap.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@use '../../styles/utilities' as *;

$spacing: rem(4px);

[part~='label'] {
@include type-category('body-1');

color: color(gray, 900);
padding-inline-start: $spacing;
}
29 changes: 29 additions & 0 deletions src/components/rating/rating.fluent.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@use '../../styles/utilities' as *;

$spacing: rem(6px);
$disabled-color: color(gray, 200) !default;
$disabled-selected-color: color(gray, 500) !default;
$disabled-label-color: color(gray, 400) !default;

[part~='label'] {
@include type-category('subtitle-2');

color: color(gray, 900);
padding-inline-start: $spacing;
}

:host([disabled]) {
[part~='symbols-wrapper'] {
color: $disabled-color;
}

[part~='label'] {
color: $disabled-label-color;
}

[part~='fraction'] {
[part~='symbols-wrapper'] {
color: $disabled-selected-color;
}
}
}
10 changes: 10 additions & 0 deletions src/components/rating/rating.indigo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@use '../../styles/utilities' as *;

$spacing: rem(5px);

[part~='label'] {
@include type-category('body-1');

color: color(gray, 900);
padding-inline-start: $spacing;
}
Loading

0 comments on commit af4c67e

Please sign in to comment.