Skip to content

Commit

Permalink
Merge pull request #1495 from chrisolsen/1204-textarea
Browse files Browse the repository at this point in the history
Textarea counter
  • Loading branch information
ArakTaiRoth authored Dec 6, 2023
2 parents da8160a + 390d1ad commit 5b41eb6
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 129 deletions.
171 changes: 171 additions & 0 deletions libs/docs/src/components/common/TextArea.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,44 @@ import { GoATextArea } from "@abgov/react-components";
lang="angular"
type="() => void"
description="Event triggered on each key press"
name="countBy"
required="true"
type="character | word"
lang="react"
description="What the count is of"
/>
<Prop
name="showCount"
type="boolean"
lang="react"
defaultValue="false"
description="Show/hide the count"
/>
<Prop
name="maxCount"
lang="react"
type="number"
description="Set the max count"
/>
<Prop
name="countby"
required="true"
type="character | word"
lang="angular"
description="What the count is of"
/>
<Prop
name="showcount"
type="boolean"
lang="angular"
defaultValue="false"
description="Show/hide the count"
/>
<Prop
name="maxcount"
lang="angular"
type="number"
description="Set the max count"
/>
</Props>

Expand Down Expand Up @@ -207,6 +245,139 @@ export const noop = () => {
</Tab>
</Tabs>

#### Word count

export const CharCountTemplate = () => {
const [value, setValue] = useState("");
return (
<GoATextArea
name="comment"
value={value}
countBy="word"
showCount={true}
onChange={(name, value) => setValue(value)}
/>
);
};

<Story name="Word count">{CharCountTemplate.bind({})}</Story>

<Tabs>
<Tab label="Web Component" hidden={true}>
<CodeSnippet
code={`<goa-textarea name="firstname" showcount="true" />`}
lang="html"
/>
</Tab>
<Tab label="Angular">
<CodeSnippet
lang="html"
code={`
<goa-textarea
goaValue
name="comment"
countby="word"
showcount="true"
[(ngModel)]="val"
></goa-textarea>
`}
/>
<CodeSnippet
lang="ts"
code={`
export class SomeComponent {
val = "";
}
`}
/>
</Tab>
<Tab label="React">
<CodeSnippet
code={`
const [value, setValue] = useState('');
return (
<GoATextArea
name="firstname"
value={value}
countBy="word"
showCount={true}
onChange={(name, value) => setValue(value)}
/>
)
`}
lang="tsx"
/>
</Tab>
</Tabs>

#### Character count with limit

export const CharCountWithLimitTemplate = () => {
const [value, setValue] = useState("");
return (
<GoATextArea
name="comment"
value={value}
countBy="character"
maxCount={20}
onChange={(name, value) => setValue(value)}
/>
);
};

<Story name="Character count with limit">
{CharCountWithLimitTemplate.bind({})}
</Story>

<Tabs>
<Tab label="Web Component" hidden={true}>
<CodeSnippet
code={`<goa-textarea name="firstname" maxcount="20" />`}
lang="html"
/>
</Tab>
<Tab label="Angular">
<CodeSnippet
lang="html"
code={`
<goa-textarea
goaValue
name="comment"
countby="character"
maxcount="20"
[(ngModel)]="val"
></goa-textarea>
`}
/>
<CodeSnippet
lang="ts"
code={`
export class SomeComponent {
val = "";
}
`}
/>
</Tab>
<Tab label="React">
<CodeSnippet
code={`
const [value, setValue] = useState('');
return (
<GoATextArea
name="firstname"
value={value}
countBy="character"
maxCount={20}
onChange={(name, value) => setValue(value)}
/>
)
`}
lang="tsx"
/>
</Tab>
</Tabs>


#### Disabled

<Story name="Disabled">
Expand Down
11 changes: 7 additions & 4 deletions libs/react-components/src/lib/textarea/textarea.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ describe("TextArea", () => {
rows={10}
placeholder="textarea-placeholder"
disabled={true}
showCounter={true}
maxCharCount={50}
countBy="word"
showCount={true}
maxCount={50}
mt="s"
mr="m"
mb="l"
Expand All @@ -27,8 +28,9 @@ describe("TextArea", () => {
expect(el.getAttribute("rows")).toBe("10");
expect(el.getAttribute("placeholder")).toBe("textarea-placeholder");
expect(el.getAttribute("disabled")).toBe("true");
expect(el.getAttribute("showcounter")).toBe("true");
expect(el.getAttribute("maxcharcount")).toBe("50");
expect(el.getAttribute("showcount")).toBe("true");
expect(el.getAttribute("countby")).toBe("word");
expect(el.getAttribute("maxcount")).toBe("50");
expect(el.getAttribute("mt")).toBe("s");
expect(el.getAttribute("mr")).toBe("m");
expect(el.getAttribute("mb")).toBe("l");
Expand All @@ -44,6 +46,7 @@ describe("TextArea", () => {
testId="textarea-testid"
name="textarea-name"
value="textarea-value"
countBy="word"
rows={10}
placeholder="textarea-placeholder"
disabled={true}
Expand Down
23 changes: 17 additions & 6 deletions libs/react-components/src/lib/textarea/textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useEffect, useRef } from "react";
import { Margins } from "../../common/styling";


type CountBy = "character" | "word";

interface WCProps extends Margins {
ref: React.Ref<HTMLTextAreaElement>;
name: string;
Expand All @@ -13,6 +16,9 @@ interface WCProps extends Margins {
maxcharcount?: number;
width?: string;
arialabel?: string;
countby?: CountBy;
showcount?: boolean;
maxcount?: number;
}

declare global {
Expand All @@ -24,6 +30,7 @@ declare global {
}
}


export interface GoATextAreaProps extends Margins {
name: string;
value: string;
Expand All @@ -32,11 +39,13 @@ export interface GoATextAreaProps extends Margins {
rows?: number;
error?: boolean;
disabled?: boolean;
showCounter?: boolean;
maxCharCount?: number;
width?: string;
testId?: string;
ariaLabel?: string;
countBy?: CountBy;
showCount?: boolean;
maxCount?: number;

onChange: (name: string, value: string) => void;
onKeyPress?: (name: string, value: string, key: string) => void;
}
Expand All @@ -47,8 +56,9 @@ export function GoATextarea({
placeholder,
rows,
disabled,
showCounter,
maxCharCount,
countBy,
showCount,
maxCount,
width,
testId,
error,
Expand Down Expand Up @@ -93,8 +103,9 @@ export function GoATextarea({
value={value}
rows={rows}
disabled={disabled}
showcounter={showCounter}
maxcharcount={maxCharCount}
countby={countBy}
showcount={showCount}
maxcount={maxCount}
width={width}
error={error}
data-testid={testId}
Expand Down
52 changes: 31 additions & 21 deletions libs/web-components/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function validateRequired(componentName: string, props: Record<string, un
if (!prop[1]) {
console.warn(`${componentName}: ${prop[0]} is required`);
}
})
});
}

// To avoid console errors due to late binding, we need to use setTimeout before calling typeValidator
Expand All @@ -41,34 +41,44 @@ export function typeValidator(
}

export function getTimestamp(val?: Date) {
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const now = val || new Date();
const hour24 = now.getHours();
const min0 = now.getMinutes()
const min0 = now.getMinutes();

const date = now.getDate()
const date = now.getDate();
const month = months[now.getMonth()];
const year = now.getFullYear();
const hour =
hour24 === 0 && 12
|| hour24 > 12 && hour24 - 12
|| hour24;
const meridium =
hour24 === 0 && "AM"
|| hour24 >= 12 && "PM"
|| "AM";
const min =
min0 < 10 && `0${min0}`
|| min0;
const ordinal
= date % 10 === 1 && date !== 11 && "st"
|| date % 10 === 2 && date !== 12 && "nd"
|| date % 10 === 3 && date !== 13 && "rd"
|| "th";
const hour = (hour24 === 0 && 12) || (hour24 > 12 && hour24 - 12) || hour24;
const meridium = (hour24 === 0 && "AM") || (hour24 >= 12 && "PM") || "AM";
const min = (min0 < 10 && `0${min0}`) || min0;
const ordinal =
(date % 10 === 1 && date !== 11 && "st") ||
(date % 10 === 2 && date !== 12 && "nd") ||
(date % 10 === 3 && date !== 13 && "rd") ||
"th";

return `${month} ${date}${ordinal} ${year}, ${hour}:${min} ${meridium}`
return `${month} ${date}${ordinal} ${year}, ${hour}:${min} ${meridium}`;
}

export function cssVar(name: string, value: string | number): string {
return value ? `${name}: ${value};` : "";
}

export function pluralize(word: string, count: number) {
if (count === 1) return word;
return `${word}s`;
}
3 changes: 2 additions & 1 deletion libs/web-components/src/components/form-item/FormItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
</div>
{#if error}
<div class="error-msg">
<goa-icon type="warning" size="small" theme="filled" style="pointer-events: none;" />
<goa-icon type="warning" size="small" theme="filled" mt="2xs" />
{error}
</div>
{/if}
Expand Down Expand Up @@ -114,6 +114,7 @@
.error-msg {
display: inline-flex;
align-items: flex-start;
gap: 0.25rem;
font-size: var(--goa-font-size-2);
color: var(--goa-color-interactive-error);
Expand Down
Loading

0 comments on commit 5b41eb6

Please sign in to comment.