Skip to content
This repository has been archived by the owner on Aug 6, 2024. It is now read-only.

feat: Added editable text #665

Merged
merged 4 commits into from
Oct 27, 2023
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
40 changes: 31 additions & 9 deletions packages/design-system/src/Text/Text.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
import React from "react";
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { Meta, StoryObj } from "@storybook/react";
import { useArgs } from "@storybook/preview-api";

import { Text } from "./index";

export default {
title: "Design System/Text",
component: Text,
} as ComponentMeta<typeof Text>;
} as Meta<typeof Text>;

// eslint-disable-next-line react/function-component-definition
const Template: ComponentStory<typeof Text> = (args) => {
return <Text {...args} />;
type Story = StoryObj<typeof Text>;

export const TextStory: Story = {
name: "Text",
args: {
children: "How vexingly quick daft zebras jump!",
},
};

export const TextStory = Template.bind({});
TextStory.storyName = "Text";
TextStory.args = {
children: "How vexingly quick daft zebras jump!",
export const EditableTextStory: Story = {
name: "Editable Text",
args: {
children: "How vexingly quick daft zebras jump!",
isEditable: true,
kind: "body-m",
},
render: function Render(args) {
const [text, setText] = React.useState(args.children);

return (
<Text
{...args}
onChange={(e) => {
setText(e.target.value);
}}
>
{text}
</Text>
);
},
};
69 changes: 69 additions & 0 deletions packages/design-system/src/Text/Text.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ const Kind = {
export const StyledText = styled.span<{
color?: string;
kind?: TextKind;
isBold?: boolean;
isItalic?: boolean;
isUnderlined?: boolean;
isStriked?: boolean;
isEditable?: boolean;
}>`
${TypographyScales}
${Variables}
Expand All @@ -138,4 +143,68 @@ export const StyledText = styled.span<{
/* line-height: var(--line-height); */
letter-spacing: var(--letter-spacing);
margin: 0;
position: relative;
/* Bold style */
&[data-bold="true"] {
font-weight: var(--ads-v2-font-weight-bold);
}
/* Italic style */
&[data-italic="true"] {
font-style: italic;
}
/* Underlined style */
&[data-underlined="true"] {
text-decoration: underline;
}
/* Striked style */
&[data-striked="true"] {
text-decoration: line-through;
}
/* Editable style */
${({ isEditable }) =>
isEditable &&
`
&:after {
content: attr(data-value) " ";
visibility: hidden;
font-family: inherit;
font-size: inherit;
white-space: pre-wrap;
}
`}
`;

export const StyledEditableInput = styled.input`
font-size: inherit;
font-weight: inherit;
font-family: inherit;
line-height: inherit;
letter-spacing: inherit;
color: inherit;
text-decoration: inherit;
background-color: transparent;
border: 1px solid transparent;
border-radius: var(--ads-v2-border-radius);
outline: none;
padding: 0;
margin: 0;
position: absolute;
left: -3px;
top: -3px;
width: 100%;
padding: var(--ads-v2-spaces-1);
&:hover {
border-color: var(--ads-v2-colors-control-field-hover-border);
}
&:focus,
&:active {
border-color: var(--ads-v2-colors-control-field-default-border);
}
`;
25 changes: 19 additions & 6 deletions packages/design-system/src/Text/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import React from "react";
import clsx from "classnames";
import { TextProps } from "./Text.types";
import { StyledText } from "./Text.styles";
import { StyledEditableInput, StyledText } from "./Text.styles";
import { TextClassName } from "./Text.constants";

/*
TODO:
- ~create regular text component (copy styles)~
- create editable text with prop `editable`
- create highlight text with prop `highlight`
- add segment header style to list of styles
- create uneditable field with prop `uneditable`
*/

function Text({
children,
className,
color,
inputProps,
isEditable,
kind,
onChange,
renderAs,
...rest
}: TextProps) {
Expand All @@ -26,10 +25,24 @@ function Text({
as={renderAs}
className={clsx(TextClassName, className)}
color={color}
data-bold={rest.isBold}
data-italic={rest.isItalic}
data-striked={rest.isStriked}
data-underlined={rest.isUnderlined}
data-value={isEditable && typeof children === "string" ? children : null}
isEditable={isEditable && typeof children === "string"}
kind={kind}
{...rest}
>
{children}
{isEditable && typeof children === "string" ? (
<StyledEditableInput
onChange={onChange}
value={children}
{...inputProps}
/>
) : (
children
)}
</StyledText>
);
}
Expand Down
19 changes: 18 additions & 1 deletion packages/design-system/src/Text/Text.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type TextKind =

// Text props
export type TextProps = {
/** To change the rendering component */
/** to change the rendering component */
renderAs?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "label";
/** (try not to) pass addition classes here */
className?: string;
Expand All @@ -25,6 +25,23 @@ export type TextProps = {
kind?: TextKind;
/** the color of the text. Accepts any valid css value. */
color?: string;
/** whether the text is bold or not */
isBold?: boolean;
/** whether the text is italic or not */
isItalic?: boolean;
/** whether the text is underlined or not */
isUnderlined?: boolean;
/** whether the text is striked or not */
isStriked?: boolean;
/** whether the text is editable or not */
isEditable?: boolean;
/** onChange event for editable text */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/** input component props while isEditable is true */
inputProps?: Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"value" | "onChange"
>;
} & React.HTMLAttributes<HTMLLabelElement> &
React.HTMLAttributes<HTMLHeadingElement> &
React.HTMLAttributes<HTMLParagraphElement> &
Expand Down
Loading