Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions addon/components/o-s-s/smart/tag-input.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
</div>
{{else}}
<div class="fx-col">
<span class="hidden-span">
{{if (or this.inputValue this.isInputFocused) this.inputValue this.placeholder}}
</span>
<span class="hidden-span">{{this.hiddenSpanValue}}</span>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥷 Remove span strange escape, which lead to unconsistent behavior between classic & loading state

<Input
class="displayed-input"
@value={{this.inputValue}}
Expand Down
4 changes: 4 additions & 0 deletions addon/components/o-s-s/smart/tag-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export default class OSSSmartTagInput extends Component<OSSSmartTagInputArgs> {
return this.args.placeholder ?? this.intl.t('oss-components.smart.tag_input.placeholder');
}

get hiddenSpanValue(): string {
return this.inputValue || this.isInputFocused ? this.inputValue : this.placeholder;
}

@action
registerElement(element: HTMLElement): void {
this.element = element;
Expand Down
23 changes: 23 additions & 0 deletions addon/components/o-s-s/smart/text-area.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div
class="oss-smart-text-area-container {{if @hasError ' oss-smart-text-area-container--errored'}}"
{{did-insert this.registerElement}}
{{did-update this.handleUpdate @loading}}
...attributes
>
<div class="fx-row">
{{#if @loading}}
<div class="upf-input loading-placeholder fx-row fx-xalign-center">
<pre class="smart_text_animated">{{or @value @placeholder}}</pre>
</div>
{{/if}}
<Textarea
@value={{@value}}
placeholder={{@placeholder}}
disabled={{@disabled}}
rows={{this.rows}}
class="oss-textarea {{this.computedClass}}"
{{on "keyup" (fn this._onChange @value)}}
/>
</div>

</div>
121 changes: 121 additions & 0 deletions addon/components/o-s-s/smart/text-area.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { hbs } from 'ember-cli-htmlbars';
import { action } from '@storybook/addon-actions';

const ResizeTypes = ['horizontal', 'vertical', 'none', null];

export default {
title: 'Components/OSS::Smart::TextArea',
component: 'smart text-area',
argTypes: {
value: {
description: 'Value of the textarea',
table: {
type: {
summary: 'string'
},
defaultValue: { summary: 'undefined' }
},
control: { type: 'text' }
},
rows: {
description: 'Number of rows dispayed in the textarea',
table: {
type: {
summary: 'number'
},
defaultValue: { summary: 2 }
},
control: { type: 'number' }
},
resize: {
description: 'Define direction in which textarea can be resized (By default the resize is set to Both)',
table: {
type: {
summary: ResizeTypes.join('|')
},
defaultValue: { summary: 'both' }
},
options: ResizeTypes,
control: { type: 'select' }
},
disabled: {
description: 'Disable the default textarea',
table: {
type: {
summary: 'boolean'
},
defaultValue: { summary: false }
},
control: { type: 'boolean' }
},
placeholder: {
description: 'Placeholder of the textarea',
table: {
type: {
summary: 'string'
},
defaultValue: { summary: 'undefined' }
},
control: { type: 'text' }
},
loading: {
description: 'Indicates if the textarea is in a loading state',
table: {
type: {
summary: 'boolean'
},
defaultValue: { summary: false }
},
control: { type: 'boolean' }
},
hasError: {
description: 'Indicates if the textarea has an error',
table: {
type: {
summary: 'boolean'
},
defaultValue: { summary: false }
},
control: { type: 'boolean' }
},
onChange: {
description: 'Method called every time the textarea is updated',
table: {
category: 'Actions',
type: {
summary: 'onChange(value: string): void'
}
}
}
},
parameters: {
docs: {
description: {
component: 'The OSS version of the textarea component.'
}
}
}
};

const defaultArgs = {
value: 'John',
rows: 2,
resize: null,
disabled: false,
placeholder: 'this is the placeholder',
hasError: false,
loading: false,
onChange: action('onChange')
};

const DefaultUsageTemplate = (args) => ({
template: hbs`
<OSS::Smart::TextArea @value={{this.value}} @disabled={{this.disabled}} @placeholder={{this.placeholder}}
@hasError={{this.hasError}} @onChange={{this.onChange}} @rows={{this.rows}}
@resize={{this.resize}} @loading={{this.loading}}/>
`,
context: args
});

export const BasicUsage = DefaultUsageTemplate.bind({});
BasicUsage.args = defaultArgs;
43 changes: 43 additions & 0 deletions addon/components/o-s-s/smart/text-area.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { action } from '@ember/object';
import { isEmpty } from '@ember/utils';
import { tracked } from '@glimmer/tracking';
import { runSmartGradientAnimation } from '@upfluence/oss-components/utils/run-smart-gradient-animation';
import type { OSSTextAreaArgs, textAreaResizeOptions } from '../text-area';
import OSSTextArea from '../text-area';

interface OSSSmartImmersiveInputComponentSignature extends OSSTextAreaArgs {
value: string;
loading: boolean;
hasError?: boolean;
}

export default class OSSSmartTextareaComponent extends OSSTextArea<OSSSmartImmersiveInputComponentSignature> {
@tracked declare element: HTMLElement;
@tracked declare textAreaElement: HTMLTextAreaElement;

@action
handleUpdate(): void {
if (!this.args.loading && !isEmpty(this.args.value)) {
runSmartGradientAnimation(this.element);
}
}

@action
registerElement(element: HTMLElement): void {
this.element = element;
}

get resize(): textAreaResizeOptions | undefined {
return this.args.resize ?? 'none';
}

get computedClass(): string {
let computedClass = super.computedClass;

if (this.args.loading) {
computedClass += ' oss-textarea--loading';
}

return computedClass;
}
}
18 changes: 12 additions & 6 deletions addon/components/o-s-s/text-area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ import { assert } from '@ember/debug';
import { action } from '@ember/object';
import Component from '@glimmer/component';

interface OSSTextAreaArgs {
export type textAreaResizeOptions = 'vertical' | 'horizontal' | 'none';

export interface OSSTextAreaArgs {
rows?: number;
resize?: 'vertical' | 'horizontal' | 'none';
resize?: textAreaResizeOptions;
value?: string;
disabled?: boolean;
errorMessage?: string;
placeholder?: string;
onChange?(value: string): void;
}

export default class OSSTextArea extends Component<OSSTextAreaArgs> {
export default class OSSTextArea<T extends OSSTextAreaArgs> extends Component<T> {
constructor(owner: unknown, args: OSSTextAreaArgs) {
super(owner, args);

Expand All @@ -28,11 +30,15 @@ export default class OSSTextArea extends Component<OSSTextAreaArgs> {
return this.args.rows || 2;
}

get resize(): textAreaResizeOptions | undefined {
return this.args.resize;
}

get computedClass(): string {
const classes: string[] = [];
if (this.args.resize === 'vertical') classes.push('oss-textarea--resize-v');
else if (this.args.resize === 'horizontal') classes.push('oss-textarea--resize-h');
else if (this.args.resize === 'none') classes.push('oss-textarea--resize-none');
if (this.resize === 'vertical') classes.push('oss-textarea--resize-v');
else if (this.resize === 'horizontal') classes.push('oss-textarea--resize-h');
else if (this.resize === 'none') classes.push('oss-textarea--resize-none');

return classes.join(' ');
}
Expand Down
1 change: 1 addition & 0 deletions app/components/o-s-s/smart/text-area.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@upfluence/oss-components/components/o-s-s/smart/text-area';
51 changes: 51 additions & 0 deletions app/styles/atoms/smart-textarea.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.oss-smart-text-area-container {
.oss-textarea-container;
flex: 1;

> div {
position: relative;
}

.loading-placeholder {
position: absolute;
height: 100%;
width: 100%;
pointer-events: none;
display: flex;
align-items: flex-start;
flex-direction: column;
}

.smart_text_animated {
background: var(--color-gray-400);
background: linear-gradient(
130deg,
var(--color-gray-400) 18%,
var(--color-gray-300) 25%,
rgba(250, 198, 255, 1) 56%,
var(--color-primary-100) 62%,
var(--color-white) 66%,
rgba(250, 198, 255, 0.58) 68%,
var(--color-gray-300) 73%,
var(--color-gray-400) 85%
);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: smart_loading_text_animation 3.5s ease-in-out infinite;
background-size: 600% 100%;
padding: var(--spacing-px-6) 0px;

border: 0;
font-family: var(--font-family-stack);
.font-size-sm;
}

.oss-textarea {
transition: all 0s;
}

.oss-textarea--loading {
visibility: hidden;
}
}
1 change: 1 addition & 0 deletions app/styles/oss-components.less
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
@import 'atoms/smart/logo';
@import 'atoms/smart/tag';
@import 'atoms/smart/tag-input';
@import 'atoms/smart-textarea';
@import 'molecules/progress-bar';
@import 'molecules/select';
@import 'molecules/nav-tab';
Expand Down
8 changes: 8 additions & 0 deletions tests/dummy/app/controllers/smart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export default class Smart extends Controller {
];
@tracked smartTags: { value: string; type: TagType }[] = [];
@tracked inputValue: string = '';
@tracked textAreaValue: string = '';
@tracked multilinePlaceholder: string = 'Small placeholder\nwith multiple\nlines';

constructor() {
super(...arguments);
Expand Down Expand Up @@ -190,6 +192,12 @@ export default class Smart extends Controller {
return '';
}

@action
onTextAreaChange(value: string): void {
console.log('Text area value changed:', value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgotten log

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in dummy app :)

this.textAreaValue = value;
}

@action
fakeLoadData(): void {
this.loading = true;
Expand Down
20 changes: 20 additions & 0 deletions tests/dummy/app/templates/smart.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
<span class="font-color-gray-500 font-size-xs text-style-italic">(also they might be smarter than you who knows)</span>
</div>

<div
class="fx-col fx-1 background-color-white border border-color-default border-radius-md padding-px-12 fx-gap-px-12"
>
<div class="font-size-md font-weight-semibold">
Text-area
</div>
<div class="fx-col fx-gap-px-24">
<div class="fx-row fx-gap-px-24 fx-xalign-center">
<OSS::Button @label="Toggle loading" {{on "click" this.toggleLoading}} />
<OSS::Smart::TextArea
@value={{this.textAreaValue}}
@onChange={{this.onTextAreaChange}}
@rows={{7}}
@placeholder={{this.multilinePlaceholder}}
@loading={{this.loading}}
/>
</div>
</div>
</div>

<div
class="fx-col fx-1 background-color-white border border-color-default border-radius-md padding-px-12 fx-gap-px-12"
>
Expand Down
Loading
Loading