Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a8771260b |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@status-im/components": patch
|
||||
---
|
||||
|
||||
fix `<DropdowMenu.SubTrigger />` expanded state
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@status-im/components": patch
|
||||
---
|
||||
|
||||
add `<DropdownMenu.Label />`
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@status-im/components": patch
|
||||
---
|
||||
|
||||
add dark grey dropdown button
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@status-im/components": patch
|
||||
---
|
||||
|
||||
fix `<Button />` text alignment
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@status-im/components": patch
|
||||
---
|
||||
|
||||
Add `<Switch />` and `<DropdownMenu.SwitchItem />`
|
||||
Vendored
+6
-2
@@ -9,6 +9,10 @@
|
||||
],
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
|
||||
["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
|
||||
]
|
||||
["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
|
||||
"clsx\\(([^)]*)\\)"
|
||||
],
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ This monorepo contains packages for building web applications in the Status ecos
|
||||
|
||||
## Packages
|
||||
|
||||
| Name | `npm` | Description |
|
||||
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`@status-im/components`](./packages/components) | [](https://www.npmjs.com/package/@status-im/components) | Component library built with Radix UI, React Aria, Tailwind CSS. |
|
||||
| [`@status-im/js`](./packages/status-js) | [](https://www.npmjs.com/package/@status-im/js) | Libary for Waku protocol integration and blockchain interactions. |
|
||||
| [`@status-im/icons`](./packages/icons) | [](https://www.npmjs.com/package/@status-im/icons) | Auto-generated icon library based on our [design system](https://www.figma.com/design/qLLuMLfpGxK9OfpIavwsmK/Iconset?node-id=3239-987&node-type=frame&t=0h8iIiZ3Sf0g4MRV-11). |
|
||||
| [`@status-im/colors`](./packages/colors) | [](https://www.npmjs.com/package/@status-im/colors) | Auto-generated color palette based on our [design system](https://www.figma.com/design/v98g9ZiaSHYUdKWrbFg9eM/Foundations?node-id=619-5995&node-type=canvas&m=dev). |
|
||||
| [`@status-im/eslint-config`](./packages/eslint-config) | [](https://www.npmjs.com/package/@status-im/eslint-config) | Shared ESLint configuration for consistent code style across projects. |
|
||||
| Name | `npm` | Description |
|
||||
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`@status-im/components`](./packages/components) | [](https://www.npmjs.com/package/@status-im/components) | Component library built with Radix UI, React Aria, Tailwind CSS. |
|
||||
| [`@status-im/js`](./packages/status-js) | [](https://www.npmjs.com/package/@status-im/js) | Libary for Waku protocol integration and blockchain interactions. |
|
||||
| [`@status-im/icons`](./packages/icons) | [](https://www.npmjs.com/package/@status-im/icons) | Auto-generated icon library based on our [design system](https://www.figma.com/design/qLLuMLfpGxK9OfpIavwsmK/Iconset?node-id=3239-987&node-type=frame&t=0h8iIiZ3Sf0g4MRV-11). |
|
||||
| [`@status-im/colors`](./packages/colors) | [](https://www.npmjs.com/package/@status-im/colors) | Auto-generated color palette based on our [design system](https://www.figma.com/design/v98g9ZiaSHYUdKWrbFg9eM/Foundations?node-id=619-5995&node-type=canvas&m=dev). |
|
||||
| [`@status-im/eslint-config`](./packages/eslint-config) | | Shared ESLint configuration for consistent code style across projects. |
|
||||
|
||||
## Apps
|
||||
test
|
||||
|
||||
| Name | Description |
|
||||
| -------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| [`./apps/connector`](./apps/connector) | Status Desktop Wallet extended to decentralised applications in your browser. |
|
||||
|
||||
Vendored
+21
-85
@@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.9.11'
|
||||
|
||||
def changesDetected = false
|
||||
library 'status-jenkins-lib@v1.9.1'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
@@ -29,109 +27,47 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Check Changed Files') {
|
||||
when {
|
||||
changeset pattern: "apps/connector/**", comparator: "GLOB"
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
changesDetected = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Install') {
|
||||
when {
|
||||
expression { changesDetected }
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/apps/connector") {
|
||||
script {
|
||||
nix.shell(
|
||||
'yarn install --frozen-lockfile',
|
||||
pure: false,
|
||||
entryPoint: "${env.WORKSPACE}/apps/connector/shell.nix"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
steps { script {
|
||||
nix.shell('yarn install --frozen-lockfile', pure: false)
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
when {
|
||||
expression { changesDetected }
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/apps/connector") {
|
||||
script {
|
||||
nix.shell(
|
||||
'yarn build:chrome',
|
||||
pure: false,
|
||||
entryPoint: "${env.WORKSPACE}/apps/connector/shell.nix"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
steps { script {
|
||||
nix.shell('yarn build:chrome', pure: false)
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Zip') {
|
||||
when {
|
||||
expression { changesDetected }
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/apps/connector") {
|
||||
zip(
|
||||
zipFile: env.ZIP_NAME,
|
||||
dir: 'build/chrome-mv3-prod',
|
||||
archive: false,
|
||||
)
|
||||
}
|
||||
zip(
|
||||
zipFile: env.ZIP_NAME,
|
||||
dir: 'build/chrome-mv3-prod',
|
||||
archive: false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
stage('Archive') {
|
||||
when {
|
||||
expression { changesDetected }
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/apps/connector") {
|
||||
archiveArtifacts(
|
||||
artifacts: env.ZIP_NAME,
|
||||
fingerprint: true,
|
||||
)
|
||||
}
|
||||
archiveArtifacts(
|
||||
artifacts: env.ZIP_NAME,
|
||||
fingerprint: true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
stage('Upload') {
|
||||
when {
|
||||
expression { changesDetected }
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/apps/connector") {
|
||||
script {
|
||||
env.PKG_URL = s5cmd.upload(env.ZIP_NAME)
|
||||
}
|
||||
}
|
||||
}
|
||||
steps { script {
|
||||
env.PKG_URL = s5cmd.upload(env.ZIP_NAME)
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
if(changesDetected) {
|
||||
github.notifyPR(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
failure {
|
||||
script {
|
||||
if(changesDetected) {
|
||||
github.notifyPR(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
cleanup { cleanWs() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"name": "connector",
|
||||
"name": "status-browser-extension",
|
||||
"version": "0.0.1",
|
||||
"license": "MPL-2.0",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/status-im/status-web.git",
|
||||
"directory": "apps/connector"
|
||||
"url": "https://github.com/status-im/status-browser-extension.git"
|
||||
},
|
||||
"scripts": {
|
||||
"dev:chrome": "plasmo dev --target=chrome-mv3",
|
||||
|
||||
@@ -1,53 +1,5 @@
|
||||
# @status-im/components
|
||||
|
||||
## 1.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e9979fd: updates icon color for missing compound variants
|
||||
- bf14368: add `type="account"` to `<ContextTag />`
|
||||
|
||||
## 1.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7f21132: fix `<Shortcut />`icon prop and symbol centering
|
||||
|
||||
## 1.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 3ad28ea: chore: Remove flex-1 class from button component (#602)
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a3f9252: fix `<Button />` icon color for blur variant
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8f1980e: Update fontSize in tailwind.config.ts
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 15c9640: Switch icon button from aria button to regular button
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 447cce7: fix `<DropdowMenu.SubTrigger />` expanded state
|
||||
- 1ce026c: add `<DropdownMenu.Label />`
|
||||
- 4e53b3e: Fix tag and tabs
|
||||
- 273db4e: add dark grey dropdown button
|
||||
- 4452f05: fix `<Button />` text alignment
|
||||
- 433558a: Add `<Switch />` and `<DropdownMenu.SwitchItem />`
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@status-im/components",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.0",
|
||||
"license": "MPL-2.0",
|
||||
"sideEffects": [
|
||||
"*.css"
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import { Fragment } from 'react'
|
||||
|
||||
import { PlaceholderIcon } from '@status-im/icons/20'
|
||||
|
||||
import { Button } from './button'
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
@@ -55,22 +51,7 @@ const meta: Meta<
|
||||
).map(variant => (
|
||||
<div key={variant} className="flex items-center gap-4">
|
||||
{(['40', '32', '24'] as const).map(size => (
|
||||
<Fragment key={size}>
|
||||
<Button {...args} variant={variant} size={size} />
|
||||
{/* With icon */}
|
||||
<Button
|
||||
{...args}
|
||||
size={size}
|
||||
variant={variant}
|
||||
iconBefore={<PlaceholderIcon />}
|
||||
/>
|
||||
<Button
|
||||
aria-label="Button with icon only"
|
||||
size={size}
|
||||
variant={variant}
|
||||
icon={<PlaceholderIcon />}
|
||||
/>
|
||||
</Fragment>
|
||||
<Button key={size} {...args} variant={variant} size={size} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -14,7 +14,7 @@ type Variants = VariantProps<typeof styles>
|
||||
type Props = {
|
||||
size?: Variants['size']
|
||||
variant?: Variants['variant']
|
||||
onPress?: (event: React.MouseEvent<HTMLButtonElement>) => void
|
||||
onPress?: () => void
|
||||
} & (
|
||||
| {
|
||||
children: React.ReactNode
|
||||
@@ -76,7 +76,7 @@ function Button(
|
||||
{iconBefore}
|
||||
</span>
|
||||
)}
|
||||
<span className="whitespace-nowrap">{children}</span>
|
||||
<span className="flex-1 whitespace-nowrap">{children}</span>
|
||||
{iconAfter && (
|
||||
<span className={iconStyles({ size, placement: 'after', variant })}>
|
||||
{iconAfter}
|
||||
@@ -143,18 +143,16 @@ const iconStyles = cva({
|
||||
variant: {
|
||||
primary: ['text-blur-white/70'],
|
||||
positive: ['text-blur-white/70'],
|
||||
grey: [
|
||||
grey: ['text-neutral-50'],
|
||||
darkGrey: [
|
||||
'text-neutral-50',
|
||||
'blur:text-neutral-80/40',
|
||||
'dark:text-neutral-40',
|
||||
'blur:dark:text-white-40',
|
||||
'blur:dark:text-neutral-80/40',
|
||||
],
|
||||
darkGrey: ['text-neutral-40'],
|
||||
outline: [
|
||||
'text-neutral-50',
|
||||
'blur:text-neutral-80/40',
|
||||
'dark:text-neutral-40',
|
||||
'blur:dark:text-white-40',
|
||||
'blur:dark:text-neutral-80/40',
|
||||
],
|
||||
ghost: ['text-neutral-50'],
|
||||
danger: ['text-blur-white/70'],
|
||||
@@ -193,41 +191,11 @@ const iconStyles = cva({
|
||||
placement: 'after',
|
||||
className: '-mr-0.5',
|
||||
},
|
||||
{
|
||||
variant: 'grey',
|
||||
iconOnly: true,
|
||||
className: '!text-neutral-100 dark:!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'outline',
|
||||
iconOnly: true,
|
||||
className: '!text-neutral-100 dark:!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'darkGrey',
|
||||
iconOnly: true,
|
||||
className: '!text-neutral-100 dark:!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'ghost',
|
||||
iconOnly: true,
|
||||
className: '!text-neutral-100 dark:!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'primary',
|
||||
iconOnly: true,
|
||||
className: '!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'positive',
|
||||
iconOnly: true,
|
||||
className: '!text-white-100',
|
||||
},
|
||||
{
|
||||
variant: 'danger',
|
||||
iconOnly: true,
|
||||
className: '!text-white-100',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ const ContextTagVariant = (props: Props) => {
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ContextTag {...props} type="account" label="Account name" emoji="🐷" />
|
||||
<ContextTag
|
||||
{...props}
|
||||
type="icon"
|
||||
|
||||
@@ -3,8 +3,6 @@ import { cloneElement, forwardRef } from 'react'
|
||||
import { cva, cx } from 'cva'
|
||||
import { match } from 'ts-pattern'
|
||||
|
||||
import { Avatar } from '../avatar'
|
||||
|
||||
import type { IconElement } from '../types'
|
||||
import type { VariantProps } from 'cva'
|
||||
|
||||
@@ -17,10 +15,10 @@ type Props = {
|
||||
| { type: 'community'; label: string; icon: IconElement }
|
||||
| { type: 'token'; label: string; icon: IconElement }
|
||||
| { type: 'network'; label: string; icon: IconElement }
|
||||
| { type: 'account'; label: string; emoji: string }
|
||||
| { type: 'icon'; label: string; icon: IconElement }
|
||||
)
|
||||
// | { type: 'user'; user: { name: string; src: string } }
|
||||
// | { type: 'account'; account: { name: string; emoji: string } }
|
||||
// | {
|
||||
// type: 'group'
|
||||
// group: {
|
||||
@@ -38,7 +36,7 @@ type Props = {
|
||||
|
||||
const baseStyles = cva({
|
||||
base: [
|
||||
'inline-flex w-fit cursor-default items-center',
|
||||
'inline-flex w-fit cursor-default items-center rounded-full',
|
||||
'font-medium text-neutral-100 dark:text-white-100',
|
||||
'bg-neutral-10 blur:bg-neutral-80/5 dark:bg-neutral-90 blur:dark:bg-white-5',
|
||||
],
|
||||
@@ -52,13 +50,6 @@ const baseStyles = cva({
|
||||
selected: {
|
||||
true: 'border border-customisation-50',
|
||||
},
|
||||
rounded: {
|
||||
'8': 'rounded-8',
|
||||
full: 'rounded-full',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
rounded: 'full',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -125,23 +116,6 @@ const ContextTag = (props: Props, ref: React.Ref<HTMLDivElement>) => {
|
||||
</div>
|
||||
)
|
||||
})
|
||||
.with({ type: 'account' }, ({ label, emoji }) => {
|
||||
return (
|
||||
<div {...rest} ref={ref} className={baseStyles({ size, rounded: '8' })}>
|
||||
<span className={iconStyles({ size, rounded: '6', offset: size })}>
|
||||
<Avatar
|
||||
type="account"
|
||||
size={match(size)
|
||||
.with('32', () => '28' as const)
|
||||
.otherwise(() => '20' as const)}
|
||||
name={label}
|
||||
emoji={emoji}
|
||||
/>
|
||||
</span>
|
||||
<span>{label}</span>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
.with({ type: 'icon' }, ({ icon, label }) => {
|
||||
return (
|
||||
<div {...rest} ref={ref} className={baseStyles({ size })}>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { BoldIcon } from '@status-im/icons/20'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
|
||||
import { IconButton } from './icon-button'
|
||||
|
||||
@@ -11,13 +10,7 @@ const sizes = ['40', '32', '24'] as const
|
||||
const renderVariant = (variant: string) => (props: any) => (
|
||||
<div className="flex items-center gap-4">
|
||||
{sizes.map(size => (
|
||||
<IconButton
|
||||
{...props}
|
||||
key={size}
|
||||
variant={variant}
|
||||
icon={<BoldIcon />}
|
||||
onPress={action('press')}
|
||||
/>
|
||||
<IconButton {...props} key={size} variant={variant} icon={BoldIcon} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
@@ -26,7 +19,7 @@ const meta = {
|
||||
component: IconButton,
|
||||
title: 'Components/Icon Button',
|
||||
args: {
|
||||
disabled: false,
|
||||
isDisabled: false,
|
||||
},
|
||||
|
||||
parameters: {
|
||||
|
||||
@@ -3,36 +3,27 @@
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
import { cva } from 'cva'
|
||||
import { Button as AriaButton } from 'react-aria-components'
|
||||
|
||||
import type { IconElement } from '../types'
|
||||
import type { VariantProps } from 'cva'
|
||||
import type { Ref } from 'react'
|
||||
import type { ButtonProps as AriaButtonProps } from 'react-aria-components'
|
||||
|
||||
type Variants = VariantProps<typeof styles>
|
||||
|
||||
type Props = {
|
||||
type Props = AriaButtonProps & {
|
||||
variant?: Variants['variant']
|
||||
icon: IconElement
|
||||
onPress?: (event: React.MouseEvent<HTMLButtonElement>) => void
|
||||
}
|
||||
|
||||
type ButtonProps = Omit<React.ComponentPropsWithoutRef<'button'>, 'children'>
|
||||
|
||||
const IconButton = (
|
||||
props: Props & ButtonProps,
|
||||
ref: Ref<HTMLButtonElement>,
|
||||
) => {
|
||||
const { variant = 'default', onPress: onClick, icon, ...buttonProps } = props
|
||||
const IconButton = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||
const { variant = 'default', icon, ...buttonProps } = props
|
||||
|
||||
return (
|
||||
<button
|
||||
{...buttonProps}
|
||||
onClick={onClick}
|
||||
ref={ref}
|
||||
className={styles({ variant })}
|
||||
>
|
||||
<AriaButton {...buttonProps} ref={ref} className={styles({ variant })}>
|
||||
{icon}
|
||||
</button>
|
||||
</AriaButton>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,16 +37,16 @@ const styles = cva({
|
||||
variants: {
|
||||
variant: {
|
||||
default: [
|
||||
'border-transparent bg-neutral-10 text-neutral-50 active:border-neutral-20 active:bg-neutral-10 active:text-neutral-100 hover:bg-neutral-20',
|
||||
'dark:bg-neutral-90 dark:text-neutral-40 dark:active:border-neutral-60 dark:active:bg-neutral-80/70 dark:active:text-white-100 dark:hover:bg-neutral-80',
|
||||
'border-transparent bg-neutral-10 text-neutral-50 hover:bg-neutral-20 pressed:border-neutral-20 pressed:bg-neutral-10 pressed:text-neutral-100',
|
||||
'dark:bg-neutral-90 dark:text-neutral-40 dark:hover:bg-neutral-80 dark:pressed:border-neutral-60 dark:pressed:bg-neutral-80/70 dark:pressed:text-white-100',
|
||||
],
|
||||
outline: [
|
||||
'border-neutral-30 text-neutral-50 active:border-neutral-20 active:bg-neutral-10 active:text-neutral-100 hover:border-neutral-40',
|
||||
'dark:border-neutral-70 dark:text-neutral-40 dark:active:border-neutral-60 dark:active:bg-neutral-80/70 dark:active:text-white-100 dark:hover:bg-neutral-60',
|
||||
'border-neutral-30 text-neutral-50 hover:border-neutral-40 pressed:border-neutral-20 pressed:bg-neutral-10 pressed:text-neutral-100',
|
||||
'dark:border-neutral-70 dark:text-neutral-40 dark:hover:bg-neutral-60 dark:pressed:border-neutral-60 dark:pressed:bg-neutral-80/70 dark:pressed:text-white-100',
|
||||
],
|
||||
ghost: [
|
||||
'border-transparent text-neutral-50 active:border-neutral-20 active:bg-neutral-10 active:text-neutral-100 hover:bg-neutral-10',
|
||||
'dark:text-neutral-40 dark:active:border-neutral-60 dark:active:bg-neutral-80/70 dark:active:text-white-100 dark:hover:bg-neutral-80/70',
|
||||
'border-transparent text-neutral-50 hover:bg-neutral-10 pressed:border-neutral-20 pressed:bg-neutral-10 pressed:text-neutral-100',
|
||||
'dark:text-neutral-40 dark:hover:bg-neutral-80/70 dark:pressed:border-neutral-60 dark:pressed:bg-neutral-80/70 dark:pressed:text-white-100',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ const variants = ['primary', 'secondary', 'gray'] as const
|
||||
// eslint-disable-next-line react/display-name
|
||||
const renderVariant = (variant: (typeof variants)[number]) => (props: any) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<Shortcut {...props} variant={variant} icon={<CommandIcon />} />
|
||||
<Shortcut {...props} variant={variant} icon={CommandIcon} />
|
||||
<Shortcut {...props} variant={variant} symbol="K" />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { cloneElement, forwardRef } from 'react'
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
import { match, P } from 'ts-pattern'
|
||||
|
||||
import { cva } from '../utils/variants'
|
||||
|
||||
import type { IconElement } from '../types'
|
||||
import type { VariantProps } from '../utils/variants'
|
||||
|
||||
const styles = cva({
|
||||
base: 'grid size-4 flex-shrink-0 place-items-center rounded-6 border',
|
||||
base: 'flex size-4 flex-shrink-0 items-center justify-center rounded-6 border',
|
||||
variants: {
|
||||
variant: {
|
||||
primary: [
|
||||
@@ -33,7 +32,7 @@ const styles = cva({
|
||||
type Props = VariantProps<typeof styles> &
|
||||
(
|
||||
| {
|
||||
icon: IconElement
|
||||
icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
||||
symbol?: never
|
||||
}
|
||||
| {
|
||||
@@ -43,17 +42,15 @@ type Props = VariantProps<typeof styles> &
|
||||
)
|
||||
|
||||
const Shortcut = (props: Props, ref: React.Ref<HTMLDivElement>) => {
|
||||
const { variant = 'primary' } = props
|
||||
const { variant = 'primary', ...rest } = props
|
||||
|
||||
return (
|
||||
<div className={styles({ variant })} ref={ref}>
|
||||
<div className={styles({ variant })} ref={ref} {...rest}>
|
||||
{match(props)
|
||||
.with({ symbol: P.string }, ({ symbol }) => (
|
||||
<span className="text-11 font-medium">{symbol}</span>
|
||||
))
|
||||
.with({ icon: P._ }, ({ icon }) =>
|
||||
cloneElement(icon, { className: 'size-3' }),
|
||||
)
|
||||
.with({ icon: P._ }, ({ icon: Icon }) => <Icon className="size-3" />)
|
||||
.exhaustive()}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -101,7 +101,7 @@ Trigger.displayName = Tabs.Trigger.displayName
|
||||
const tabStyles = cva({
|
||||
base: [
|
||||
'group inline-flex items-center gap-1 whitespace-nowrap',
|
||||
'disabled:opacity-[.3]',
|
||||
'disabled:pointer-events-none disabled:opacity-[.3]',
|
||||
],
|
||||
variants: {
|
||||
variant: {
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { PlaceholderIcon } from '@status-im/icons/20'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
|
||||
import { Tag } from './tag'
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
const meta: Meta<typeof Tag> = {
|
||||
const meta = {
|
||||
component: Tag,
|
||||
title: 'Components/Tag',
|
||||
args: {
|
||||
label: 'Tag',
|
||||
disabled: false,
|
||||
selected: false,
|
||||
icon: <PlaceholderIcon />,
|
||||
iconPlacement: 'left',
|
||||
},
|
||||
@@ -26,17 +24,17 @@ const meta: Meta<typeof Tag> = {
|
||||
render: props => (
|
||||
<div className="flex flex-col items-start gap-4">
|
||||
<Tag {...props} />
|
||||
<Tag {...props} onPress={action('pressed')} selected />
|
||||
<Tag {...props} onPress={action('pressed')} disabled />
|
||||
<Tag {...props} selected />
|
||||
<Tag {...props} disabled />
|
||||
<Tag {...props} size="24" />
|
||||
<Tag {...props} size="24" onPress={action('pressed')} selected />
|
||||
<Tag {...props} size="24" onPress={action('pressed')} disabled />
|
||||
<Tag {...props} size="24" selected />
|
||||
<Tag {...props} size="24" disabled />
|
||||
<Tag {...props} icon={undefined} />
|
||||
<Tag {...props} label={undefined} />
|
||||
<Tag {...props} iconPlacement="right" />
|
||||
</div>
|
||||
),
|
||||
}
|
||||
} satisfies Meta<typeof Tag>
|
||||
|
||||
type Story = StoryObj<typeof Tag>
|
||||
|
||||
|
||||
@@ -8,83 +8,52 @@ import type { Ref } from 'react'
|
||||
|
||||
type Variants = VariantProps<typeof styles>
|
||||
|
||||
type Props = {
|
||||
type Props = React.ComponentProps<'button'> & {
|
||||
size?: Variants['size']
|
||||
label?: string
|
||||
icon?: IconElement
|
||||
iconPlacement?: 'left' | 'right'
|
||||
selected?: boolean
|
||||
onPress?: () => void
|
||||
}
|
||||
|
||||
type ButtonProps = {
|
||||
onPress: (event: React.MouseEvent<HTMLButtonElement>) => void
|
||||
selected?: boolean
|
||||
disabled?: boolean
|
||||
} & Omit<React.ComponentPropsWithoutRef<'button'>, 'children'>
|
||||
|
||||
type DivProps = Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>
|
||||
|
||||
function Tag(
|
||||
props: Props & (ButtonProps | DivProps),
|
||||
ref: Ref<HTMLButtonElement | HTMLDivElement>,
|
||||
) {
|
||||
const Tag = (props: Props, ref: Ref<HTMLButtonElement>) => {
|
||||
const {
|
||||
size = '32',
|
||||
icon,
|
||||
iconPlacement = 'left',
|
||||
label,
|
||||
...rest
|
||||
selected = false,
|
||||
disabled = false,
|
||||
onPress: onClick,
|
||||
...buttonProps
|
||||
} = props
|
||||
|
||||
const iconOnly = Boolean(icon && !label)
|
||||
|
||||
const content = (
|
||||
<>
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
{...buttonProps}
|
||||
disabled={disabled}
|
||||
ref={ref}
|
||||
data-selected={selected}
|
||||
className={styles({ size, selected, disabled, iconOnly })}
|
||||
>
|
||||
{icon && iconPlacement === 'left' && (
|
||||
<span className={iconStyles({ size, placement: 'left', iconOnly })}>
|
||||
{cloneElement(icon)}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{label && <span className="flex-1 whitespace-nowrap">{label}</span>}
|
||||
|
||||
{icon && iconPlacement === 'right' && (
|
||||
<span className={iconStyles({ size, placement: 'right', iconOnly })}>
|
||||
{cloneElement(icon)}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
if ('onPress' in props) {
|
||||
const { selected, disabled, ...buttonProps } = props as ButtonProps
|
||||
|
||||
return (
|
||||
<button
|
||||
{...buttonProps}
|
||||
onClick={props.onPress}
|
||||
ref={ref as Ref<HTMLButtonElement>}
|
||||
data-selected={selected ? selected : undefined}
|
||||
className={styles({
|
||||
size,
|
||||
selected,
|
||||
disabled,
|
||||
iconOnly,
|
||||
})}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
{...(rest as DivProps)}
|
||||
ref={ref as Ref<HTMLDivElement>}
|
||||
className={styles({
|
||||
size,
|
||||
iconOnly,
|
||||
})}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -93,6 +62,8 @@ const styles = cva({
|
||||
'inline-flex shrink-0 items-center justify-center gap-1 border border-neutral-20 font-medium transition-all hover:border-neutral-30',
|
||||
'outline-none focus:outline-none focus-visible:ring-2 focus-visible:ring-customisation-50 focus-visible:ring-offset-2',
|
||||
'disabled:cursor-default disabled:opacity-[.3]',
|
||||
|
||||
// dark
|
||||
'dark:border-neutral-80 dark:text-white-100 dark:hover:border-neutral-60',
|
||||
],
|
||||
variants: {
|
||||
|
||||
@@ -34,62 +34,14 @@ export default {
|
||||
},
|
||||
|
||||
fontSize: {
|
||||
88: [
|
||||
'5.5rem',
|
||||
{
|
||||
lineHeight: '5.25rem',
|
||||
letterSpacing: '-0.1155rem',
|
||||
},
|
||||
],
|
||||
64: [
|
||||
'4rem',
|
||||
{
|
||||
lineHeight: '4.25rem',
|
||||
letterSpacing: '-0.08rem',
|
||||
},
|
||||
],
|
||||
40: [
|
||||
'2.5rem',
|
||||
{
|
||||
lineHeight: '2.75rem',
|
||||
letterSpacing: '-0.05rem',
|
||||
},
|
||||
],
|
||||
27: [
|
||||
'1.6875rem',
|
||||
{
|
||||
lineHeight: '2rem',
|
||||
letterSpacing: '-0.0354375rem',
|
||||
},
|
||||
],
|
||||
19: [
|
||||
'1.1875rem',
|
||||
{
|
||||
lineHeight: '1.75rem',
|
||||
letterSpacing: '-0.019rem',
|
||||
},
|
||||
],
|
||||
15: [
|
||||
'0.9375rem',
|
||||
{
|
||||
lineHeight: '1.359375rem',
|
||||
letterSpacing: '-0.0084375rem',
|
||||
},
|
||||
],
|
||||
13: [
|
||||
'0.8125rem',
|
||||
{
|
||||
lineHeight: '1.1375rem',
|
||||
letterSpacing: '-0.0024375rem',
|
||||
},
|
||||
],
|
||||
11: [
|
||||
'0.6875rem',
|
||||
{
|
||||
lineHeight: '0.97625rem',
|
||||
letterSpacing: '-0.0034375rem',
|
||||
},
|
||||
],
|
||||
88: ['5.5rem', { lineHeight: '5.25rem', letterSpacing: '-0.1155rem' }],
|
||||
64: ['4rem', { lineHeight: '4.25rem', letterSpacing: '-0.08rem' }],
|
||||
40: ['2.5rem', { lineHeight: '2.75rem', letterSpacing: '-0.05rem' }],
|
||||
27: ['1.6875rem', { lineHeight: '2rem', letterSpacing: '0rem' }],
|
||||
19: ['1.1875rem', { lineHeight: '1.75rem', letterSpacing: '0rem' }],
|
||||
15: ['0.9375rem', { lineHeight: '1.36rem', letterSpacing: '0rem' }],
|
||||
13: ['0.8125rem', { lineHeight: '1.1375rem', letterSpacing: '0rem' }],
|
||||
11: ['0.6875rem', { lineHeight: '1', letterSpacing: '0rem' }],
|
||||
},
|
||||
|
||||
opacity: {},
|
||||
|
||||
Reference in New Issue
Block a user