From 20f9f11fbf9b9c420707eca79baa80c2b08e73e6 Mon Sep 17 00:00:00 2001 From: marcelines Date: Fri, 2 Jun 2023 17:03:46 +0100 Subject: [PATCH] feat: adds all input variants and stars building filters for table issues --- apps/website/src/components/table-issues.tsx | 163 +++++++++++++++-- .../src/icon-button/icon-button.tsx | 2 +- .../components/src/input/input.stories.tsx | 46 +++++ packages/components/src/input/input.tsx | 164 +++++++++++++++--- 4 files changed, 337 insertions(+), 38 deletions(-) diff --git a/apps/website/src/components/table-issues.tsx b/apps/website/src/components/table-issues.tsx index 8064bf23..649a1b3a 100644 --- a/apps/website/src/components/table-issues.tsx +++ b/apps/website/src/components/table-issues.tsx @@ -1,41 +1,182 @@ -import { Avatar, Button, Tag, Text } from '@status-im/components' +import { useState } from 'react' + +import { Avatar, Button, Input, Tag, Text } from '@status-im/components' +import { DropdownMenu } from '@status-im/components/src/dropdown-menu' +import { DropdownIcon, OpenIcon, SearchIcon } from '@status-im/icons' import Link from 'next/link' const issues = [ { id: 5154, title: 'Add support for encrypted communities', - status: 'Open', + status: 'open', }, { id: 5155, title: 'Add support for encrypted communities', - status: 'Open', + status: 'open', }, { id: 4, title: 'Add support for encrypted communities', - status: 'Open', + status: 'open', }, { id: 4324, title: 'Add support for encrypted communities', - status: 'Open', + status: 'open', }, { - id: 876, + id: 134, title: 'Add support for encrypted communities', - status: 'Open', + status: 'closed', + }, + { + id: 999, + title: 'Add support for encrypted communities', + status: 'closed', + }, + { + id: 873, + title: 'Add support for encrypted communities', + status: 'open', + }, + { + id: 123, + title: 'Add support for encrypted communities', + status: 'open', + }, +] + +const authors = [ + { + id: 1, + name: 'Tobias', + avatar: + 'https://images.unsplash.com/photo-1518020382113-a7e8fc38eac9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&h=500&q=80', + }, + { + id: 2, + name: 'Arnold', + avatar: + 'https://images.unsplash.com/photo-1518020382113-a7e8fc38eac9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&h=500&q=80', + }, + { + id: 3, + name: 'Alisher', + avatar: + 'https://images.unsplash.com/photo-1518020382113-a7e8fc38eac9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&h=500&q=80', + }, + { + id: 4, + name: 'marcelines', + avatar: 'https://avatars.githubusercontent.com/u/29401404?v=4', + }, + { + id: 5, + name: 'prichodko', + avatar: 'https://avatars.githubusercontent.com/u/14926950?v=4', + }, + { + id: 6, + name: 'felicio', + avatar: 'https://avatars.githubusercontent.com/u/13265126?v=4', + }, + { + id: 7, + name: 'jkbktl', + avatar: 'https://avatars.githubusercontent.com/u/520927?v=4', }, ] export const TableIssues = () => { + const [activeTab, setActiveTab] = useState<'open' | 'closed'>('open') + + const [authorFilterText, setAuthorFilterText] = useState('') + const filteredAuthors = authors.filter(author => + author.name.toLowerCase().includes(authorFilterText.toLowerCase()) + ) + return (
-
- - 784 Open - +
+
+
+ +
+
+ +
+
+
+
+
+ + + +
+ } + size={32} + value={authorFilterText} + onChangeText={setAuthorFilterText} + /> +
+ {filteredAuthors.map(author => ( + + } + label={author.name} + onSelect={() => alert('Author: ' + author.name)} + /> + ))} + {filteredAuthors.length === 0 && ( +
+ No authors found +
+ )} +
+
+
+
+ +
+
+ +
+
+
diff --git a/packages/components/src/icon-button/icon-button.tsx b/packages/components/src/icon-button/icon-button.tsx index bd58de10..24bbed19 100644 --- a/packages/components/src/icon-button/icon-button.tsx +++ b/packages/components/src/icon-button/icon-button.tsx @@ -1,6 +1,6 @@ import { cloneElement, forwardRef } from 'react' -import { Stack, styled } from 'tamagui' +import { Stack, styled } from '@tamagui/core' import { usePressableColors } from '../hooks/use-pressable-colors' diff --git a/packages/components/src/input/input.stories.tsx b/packages/components/src/input/input.stories.tsx index 10ccabfb..39d6d52f 100644 --- a/packages/components/src/input/input.stories.tsx +++ b/packages/components/src/input/input.stories.tsx @@ -1,3 +1,7 @@ +import { useEffect, useState } from 'react' + +import { SearchIcon } from '@status-im/icons' + import { Input } from './input' import type { Meta, StoryObj } from '@storybook/react' @@ -18,4 +22,46 @@ export const Primary: Story = { }, } +const InputSearch = () => { + const [value, setValue] = useState('') + + // limit input to 100 characters just for demo purposes + useEffect(() => { + if (value.length > 100) { + setValue(value.slice(0, 100)) + } + }, [value]) + + return ( + <> + } + onClear={() => setValue('')} + label="Search" + endLabel={`${value.length}/100`} + size={40} + button={{ + label: 'Confirm', + onPress: () => alert('Confirmed!'), + }} + /> + + ) +} + +export const CompleteExample: Story = { + render: () => , +} + +export const WithError: Story = { + args: { + placeholder: 'Type something...', + error: true, + // children: 'Click me', + }, +} + export default meta diff --git a/packages/components/src/input/input.tsx b/packages/components/src/input/input.tsx index 54034d72..5ca43a5d 100644 --- a/packages/components/src/input/input.tsx +++ b/packages/components/src/input/input.tsx @@ -1,62 +1,174 @@ -import { setupReactNative, styled } from '@tamagui/core' +import { cloneElement, forwardRef } from 'react' + +import { ClearIcon } from '@status-im/icons' +import { setupReactNative, Stack, styled } from '@tamagui/core' import { focusableInputHOC } from '@tamagui/focusable' import { TextInput } from 'react-native' +import { Button } from '../button' +import { IconButton } from '../icon-button' +import { Text } from '../text' + import type { GetProps } from '@tamagui/core' +import type { Ref } from 'react' setupReactNative({ TextInput, }) -export const InputFrame = styled( +const InputFrame = styled( TextInput, { tag: 'input', name: 'Input', - borderWidth: 1, outlineWidth: 0, - borderColor: 'rgba(0, 200, 0, 1)', + borderColor: '$neutral-20', - paddingHorizontal: 30, - color: 'hsla(218, 51%, 7%, 1)', + color: '$neutral-100', placeholderTextColor: '$placeHolderColor', backgroundColor: 'transparent', - height: 32, - borderRadius: '$12', - - animation: 'fast', - // this fixes a flex bug where it overflows container minWidth: 0, - hoverStyle: { - borderColor: '$beigeHover', - }, - - focusStyle: { - borderColor: '$blueHover', - }, - variants: { blurred: { true: { placeholderTextColor: '$placeHolderColorBlurred', }, }, - }, - - defaultVariants: { - blurred: '$false', - }, + } as const, }, { isInput: true, } ) -export type InputProps = GetProps +const InputContainer = styled(Stack, { + name: 'InputContainer', + tag: 'div', + flexDirection: 'row', + alignItems: 'center', + gap: 8, -export const Input = focusableInputHOC(InputFrame) + borderWidth: 1, + borderColor: '$neutral-20', + + paddingHorizontal: 12, + + animation: 'fast', + + hoverStyle: { + borderColor: '$neutral-40', + }, + + focusStyle: { + borderColor: '$neutral-40', + }, + + pressStyle: { + borderColor: '$neutral-40', + }, + + variants: { + size: { + 40: { + height: 40, + paddingHorizontal: 16, + borderRadius: '$12', + }, + 32: { + height: 32, + paddingHorizontal: 8, + borderRadius: '$10', + }, + }, + error: { + true: { + borderColor: '$danger-50-opa-40', + }, + }, + + disabled: { + true: { + opacity: 0.3, + cursor: 'default', + }, + }, + } as const, +}) + +type Props = GetProps & { + button?: { + label: string + onPress: () => void + } + endLabel?: string + icon?: React.ReactElement + label?: string + onClear?: () => void + size?: 40 | 32 + error?: boolean +} + +const InputBase = focusableInputHOC(InputFrame) + +const _Input = (props: Props, ref: Ref) => { + const { + button, + color = '$neutral-50', + endLabel, + error, + icon, + label, + onClear, + size = 40, + value, + ...rest + } = props + return ( + + {Boolean(label || endLabel) && ( + + {label && ( + + {label} + + )} + {endLabel && ( + + {endLabel} + + )} + + )} + + {icon ? cloneElement(icon, { color }) : null} + + + {Boolean(onClear) && !!value && ( + + } + onPress={onClear} + /> + + )} + {button && ( + + )} + + + + ) +} + +const Input = forwardRef(_Input) + +export { Input } +export type { Props as InputProps }