[] = [
+ 'none',
+ 'tight',
+ 'snug',
+ 'relaxed',
+ 'loose'
+ ];
+ return (
+
+ {letterSpacings.map((spacing) => (
+
+ {spacing}
+ The quick brown fox jumps over the lazy dog
+
+ ))}
+
+ );
+ }
+};
+
+export const TextTransform: Story = {
+ render: () => {
+ const textTransform: TextProps['textTransform'][] = [
+ 'none',
+ 'capitalize',
+ 'uppercase',
+ 'lowercase'
+ ];
+ return (
+
+ {textTransform.map((transform) => (
+
+ {transform}
+ The quick brown fox jumps over the lazy dog
+
+ ))}
+
+ );
+ }
+};
+
+export const TextAlign: Story = {
+ render: () => {
+ const textAlign: TextProps['textAlign'][] = ['left', 'center', 'right'];
+ return (
+
+ {textAlign.map((align) => (
+
+ {align}
+ The quick brown fox jumps over the lazy dog
+
+ ))}
+
+ );
+ }
+};
+
+export const LineClamp: Story = {
+ render: () => {
+ return (
+
+ {simpleText}
+
+ );
+ }
+};
diff --git a/src/components/atoms/Text/Text.styles.ts b/src/components/atoms/Text/Text.styles.ts
new file mode 100644
index 0000000..85c8cca
--- /dev/null
+++ b/src/components/atoms/Text/Text.styles.ts
@@ -0,0 +1,51 @@
+import { css } from '@emotion/react';
+import styled from '@emotion/styled';
+import { TextStyledProps } from './Text.types';
+
+const getThemeColor = (theme: any, color?: string) => {
+ const colorDefault = 'inherit';
+ const themeBaseColors = ['white', 'black'];
+
+ if (!color) {
+ return colorDefault;
+ }
+
+ if (themeBaseColors.includes(color)) {
+ return theme.color[color] ?? colorDefault;
+ }
+
+ const [key, shade] = color.split('[');
+
+ if (key && shade) {
+ const shadeValue = shade.replace(']', '');
+ return theme.color[key]?.[shadeValue] ?? colorDefault;
+ }
+
+ return colorDefault;
+};
+
+export const TextStyled = styled.p`
+ ${({ theme, color, size, weight, letterSpacing, textTransform, textAlign, lineClamp }) => css`
+ color: ${getThemeColor(theme, color)};
+
+ ${weight && `font-weight: ${theme.typography.fontWeight[weight]};`}
+ ${letterSpacing && `letter-spacing: ${theme.typography.letterSpacing[letterSpacing]};`};
+ ${textTransform && `text-transform: ${textTransform};`}
+ ${textAlign && `text-align: ${textAlign};`}
+
+
+ ${size &&
+ `
+ font-size: ${theme.typography.body[size].fontSize};
+ line-height: ${theme.typography.body[size].lineHeight};
+ `}
+
+ ${lineClamp &&
+ `
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: ${lineClamp};
+ -webkit-box-orient: vertical;
+ `}
+ `};
+`;
diff --git a/src/components/atoms/Text/Text.tsx b/src/components/atoms/Text/Text.tsx
new file mode 100644
index 0000000..70a2a89
--- /dev/null
+++ b/src/components/atoms/Text/Text.tsx
@@ -0,0 +1,10 @@
+import { TextStyled } from './Text.styles';
+import { TextProps } from './Text.types';
+
+export const Text: React.FC = ({ children, as = 'p', ...props }) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/components/atoms/Text/Text.types.ts b/src/components/atoms/Text/Text.types.ts
new file mode 100644
index 0000000..ae2155f
--- /dev/null
+++ b/src/components/atoms/Text/Text.types.ts
@@ -0,0 +1,36 @@
+import {
+ TypographyBodySizes,
+ TypographyLetterSpacingSizes,
+ TypographyWeightSizes
+} from 'src/themes/types';
+
+export type TextProps = {
+ /** Elemento HTML ou componente React usado como tag principal do texto. */
+ as?: React.ElementType;
+ /** Cor do texto. Aceita apenas a chave do tema (ex: 'blue[500]'). */
+ color?: string;
+ /** Tamanho da fonte e altura da linha. */
+ size?: TypographyBodySizes;
+ /** Peso da fonte do texto. */
+ weight?: TypographyWeightSizes;
+ /** Espaçamento entre letras do texto. */
+ letterSpacing?: TypographyLetterSpacingSizes;
+ /** Estilo de capitalização do texto. */
+ textTransform?: React.CSSProperties['textTransform'];
+ /** Limite de linhas para o texto truncar. */
+ lineClamp?: number;
+ /** Alinhamento do texto. */
+ textAlign?: React.CSSProperties['textAlign'];
+ /** Define o conteúdo do texto. */
+ children?: React.ReactNode;
+};
+
+export type TextStyledProps = {
+ color?: TextProps['color'];
+ size?: TextProps['size'];
+ weight?: TextProps['weight'];
+ letterSpacing?: TextProps['letterSpacing'];
+ textTransform?: TextProps['textTransform'];
+ textAlign?: TextProps['textAlign'];
+ lineClamp?: TextProps['lineClamp'];
+};
diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts
index 8bc41cb..4d6de97 100644
--- a/src/components/atoms/index.ts
+++ b/src/components/atoms/index.ts
@@ -1 +1,2 @@
export * from './Button/Button';
+export * from './Text/Text';
diff --git a/src/themes/styles/global.ts b/src/themes/styles/global.ts
index 56b7a94..a401f53 100644
--- a/src/themes/styles/global.ts
+++ b/src/themes/styles/global.ts
@@ -3,4 +3,38 @@ import { Theme } from '../types';
export const globalStyles = (theme: Theme) => css`
@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap');
+
+ * {
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+
+ body {
+ font-family: ${theme.typography.fontFamily.sans};
+ font-size: ${theme.typography.body.lg.fontSize};
+ line-height: ${theme.typography.body.lg.lineHeight};
+ color: ${theme.color.gray[700]};
+ }
+
+ code,
+ pre {
+ font-family: ${theme.typography.fontFamily.mono};
+ }
+
+ b {
+ font-weight: ${theme.typography.fontWeight.bold};
+ }
+
+ strong {
+ font-weight: ${theme.typography.fontWeight.heavy};
+ }
+
+ i {
+ font-style: italic;
+ }
+
+ small {
+ font-size: smaller;
+ }
`;
diff --git a/src/themes/tokens/typography.ts b/src/themes/tokens/typography.ts
index dba8e41..74106a0 100644
--- a/src/themes/tokens/typography.ts
+++ b/src/themes/tokens/typography.ts
@@ -3,35 +3,26 @@ export const typography = {
sans: '"Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
mono: '"Consolas", ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace'
},
- fontSize: {
- display: {
- lg: '6rem',
- md: '5rem',
- sm: '4.5rem'
- },
- heading: {
- xxl: '4rem',
- xl: '3.5rem',
- lg: '3rem',
- md: '2.5rem',
- sm: '2rem',
- xs: '1.5rem',
- xxs: '1.25rem'
- },
- body: {
- xl: '1.125rem',
- lg: '1rem',
- md: '0.875rem',
- sm: '0.75rem',
- xs: '0.625rem'
- }
+ display: {
+ lg: { fontSize: '6rem', lineHeight: '7rem' },
+ md: { fontSize: '5rem', lineHeight: '6rem' },
+ sm: { fontSize: '4.5rem', lineHeight: '5rem' }
},
- lineHeight: {
- loose: 2.0,
- relaxed: 1.6,
- snug: 1.4,
- tight: 1.2,
- none: 1.0
+ heading: {
+ xxl: { fontSize: '4rem', lineHeight: '4.5rem' },
+ xl: { fontSize: '3.5rem', lineHeight: '4rem' },
+ lg: { fontSize: '3rem', lineHeight: '3.5rem' },
+ md: { fontSize: '2.5rem', lineHeight: '3rem' },
+ sm: { fontSize: '2rem', lineHeight: '2.5rem' },
+ xs: { fontSize: '1.5rem', lineHeight: '2rem' },
+ xxs: { fontSize: '1.25rem', lineHeight: '1.5rem' }
+ },
+ body: {
+ xl: { fontSize: '1.125rem', lineHeight: '1.375rem' },
+ lg: { fontSize: '1rem', lineHeight: '1.25rem' },
+ md: { fontSize: '0.875rem', lineHeight: '1.125rem' },
+ sm: { fontSize: '0.75rem', lineHeight: '1rem' },
+ xs: { fontSize: '0.625rem', lineHeight: '0.875rem' }
},
fontWeight: {
heavy: 900,
@@ -40,11 +31,18 @@ export const typography = {
regular: 400,
light: 300
},
+ lineHeight: {
+ loose: 2,
+ relaxed: 1.6,
+ snug: 1.4,
+ tight: 1.2,
+ none: 1
+ },
letterSpacing: {
- loose: '24%',
- relaxed: '16%',
- snug: '8%',
- tight: '4%',
- none: '0%'
+ loose: '0.24em',
+ relaxed: '0.16em',
+ snug: '0.08em',
+ tight: '0.04em',
+ none: '0em'
}
} as const;
diff --git a/src/themes/types.ts b/src/themes/types.ts
index 1755e45..4a276a7 100644
--- a/src/themes/types.ts
+++ b/src/themes/types.ts
@@ -1,5 +1,24 @@
import { designTokens } from './index';
-export type DesignTokens = typeof designTokens;
+// Theme
+export type Theme = typeof designTokens & {};
-export type Theme = DesignTokens & {};
+// Border
+
+// Breakpoint
+
+// Color
+
+// Elevation
+
+// Opacity
+
+// Spacing
+
+// Typography
+export type TypographyDisplaySizes = keyof Theme['typography']['display'];
+export type TypographyHeadingSizes = keyof Theme['typography']['heading'];
+export type TypographyBodySizes = keyof Theme['typography']['body'];
+export type TypographyWeightSizes = keyof Theme['typography']['fontWeight'];
+export type TypographyLineHeightSizes = keyof Theme['typography']['lineHeight'];
+export type TypographyLetterSpacingSizes = keyof Theme['typography']['letterSpacing'];