diff --git a/src/app/components/network-mode-badge.tsx b/src/app/components/network-mode-badge.tsx
index 0e535ffd9fb..d8067de7392 100644
--- a/src/app/components/network-mode-badge.tsx
+++ b/src/app/components/network-mode-badge.tsx
@@ -2,11 +2,12 @@ import { memo, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ChainID } from '@stacks/transactions';
-import { Flex, FlexProps, styled } from 'leather-styles/jsx';
+import { Flex, FlexProps } from 'leather-styles/jsx';
import { RouteUrls } from '@shared/route-urls';
import { useCurrentNetworkState } from '@app/store/networks/networks.hooks';
+import { Tag } from '@app/ui/components/tag/tag';
export const NetworkModeBadge = memo((props: FlexProps) => {
const navigate = useNavigate();
@@ -21,19 +22,12 @@ export const NetworkModeBadge = memo((props: FlexProps) => {
return (
navigate(RouteUrls.SelectNetwork, { relative: 'path' })}
- px="space.03"
position="relative"
zIndex={999}
{...props}
>
-
- {name}
-
+
);
});
diff --git a/src/app/components/pill.tsx b/src/app/components/pill.tsx
deleted file mode 100644
index f63281d02a5..00000000000
--- a/src/app/components/pill.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Box, BoxProps, styled } from 'leather-styles/jsx';
-
-import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';
-
-interface PillProps extends BoxProps {
- hoverLabel?: string;
- label: string;
-}
-export function Pill({ hoverLabel, label, ...props }: PillProps) {
- return (
-
-
- {label}
-
-
- );
-}
diff --git a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-list/components/psbt-input-item.tsx b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-list/components/psbt-input-item.tsx
index 2709de06da4..e93cf35756b 100644
--- a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-list/components/psbt-input-item.tsx
+++ b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-list/components/psbt-input-item.tsx
@@ -1,8 +1,8 @@
import { createMoney } from '@shared/models/money.model';
import { formatMoney } from '@app/common/money/format-money';
-import { Pill } from '@app/components/pill';
import { PsbtInput } from '@app/features/psbt-signer/hooks/use-parsed-inputs';
+import { TagWithTooltip } from '@app/ui/components/tag/tag-with-tooltip';
import { truncateMiddle } from '@app/ui/utils/truncate-middle';
import { PsbtInputOutputItemLayout } from '../../psbt-input-output-item.layout';
@@ -15,7 +15,11 @@ export function PsbtInputItem({ utxo }: { utxo: PsbtInput }) {
address={truncateMiddle(utxo.address)}
addressHoverLabel={utxo.address}
amount={formatMoney(createMoney(utxo.value, 'BTC'))}
- label={utxo.toSign ? : undefined}
+ label={
+ utxo.toSign ? (
+
+ ) : undefined
+ }
txId={truncateMiddle(utxo.txid)}
txIdHoverLabel={utxo.txid}
/>
diff --git a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-output-item.layout.tsx b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-output-item.layout.tsx
index 8eb50055d8c..3dd279b4295 100644
--- a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-output-item.layout.tsx
+++ b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-input-output-item.layout.tsx
@@ -39,9 +39,9 @@ export function PsbtInputOutputItemLayout({
side="bottom"
>
-
- {addressHoverLabel ? : null}
-
+
+ {addressHoverLabel ? : null}
+
{label}
diff --git a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-output-list/components/psbt-output-item.tsx b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-output-list/components/psbt-output-item.tsx
index e8ddb099cb4..bad99075d52 100644
--- a/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-output-list/components/psbt-output-item.tsx
+++ b/src/app/features/psbt-signer/components/psbt-inputs-and-outputs/components/psbt-output-list/components/psbt-output-item.tsx
@@ -1,8 +1,8 @@
import { createMoney } from '@shared/models/money.model';
import { formatMoney } from '@app/common/money/format-money';
-import { Pill } from '@app/components/pill';
import { PsbtOutput } from '@app/features/psbt-signer/hooks/use-parsed-outputs';
+import { TagWithTooltip } from '@app/ui/components/tag/tag-with-tooltip';
import { truncateMiddle } from '@app/ui/utils/truncate-middle';
import { PsbtInputOutputItemLayout } from '../../psbt-input-output-item.layout';
@@ -19,7 +19,11 @@ export function PsbtOutputItem({ output }: { output: PsbtOutput }) {
address={truncateMiddle(output.address)}
addressHoverLabel={output.address}
amount={formatMoney(createMoney(Number(output.value), 'BTC'))}
- label={output.toSign ? : undefined}
+ label={
+ output.toSign ? (
+
+ ) : undefined
+ }
/>
);
}
diff --git a/src/app/features/psbt-signer/components/psbt-request-details-header.tsx b/src/app/features/psbt-signer/components/psbt-request-details-header.tsx
index 11069544b9e..bc4dfb2956c 100644
--- a/src/app/features/psbt-signer/components/psbt-request-details-header.tsx
+++ b/src/app/features/psbt-signer/components/psbt-request-details-header.tsx
@@ -1,8 +1,7 @@
-import { Box, HStack, styled } from 'leather-styles/jsx';
-import { token } from 'leather-styles/tokens';
+import { HStack, styled } from 'leather-styles/jsx';
import { usePsbtSignerContext } from '@app/features/psbt-signer/psbt-signer.context';
-import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';
+import { TagWithTooltip } from '@app/ui/components/tag/tag-with-tooltip';
import { LockIcon } from '@app/ui/icons/lock-icon';
import { UnlockIcon } from '@app/ui/icons/unlock-icon';
@@ -13,37 +12,17 @@ const uncertainLabel =
export function PsbtRequestDetailsHeader() {
const { isPsbtMutable } = usePsbtSignerContext();
- const tokenLabelColor = isPsbtMutable
- ? token('colors.yellow.action-primary-default')
- : token('colors.ink.text-subdued');
return (
Transaction
-
-
-
- {isPsbtMutable ? (
-
- ) : (
-
- )}
-
-
- {isPsbtMutable ? 'Uncertain' : 'Certain'}
-
-
-
+ : }
+ label={isPsbtMutable ? 'Uncertain' : 'Certain'}
+ transparent
+ variant={isPsbtMutable ? 'warning' : 'default'}
+ />
);
}
diff --git a/src/app/pages/fund/components/fast-checkout-badge.tsx b/src/app/pages/fund/components/fast-checkout-badge.tsx
deleted file mode 100644
index 423c0660e07..00000000000
--- a/src/app/pages/fund/components/fast-checkout-badge.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { HStack, styled } from 'leather-styles/jsx';
-
-import { ZapIcon } from '@app/ui/icons/zap-icon';
-
-export function FastCheckoutBadge() {
- return (
-
-
-
- Fast checkout
-
-
- );
-}
diff --git a/src/app/pages/fund/components/fiat-provider-item.tsx b/src/app/pages/fund/components/fiat-provider-item.tsx
index b94bdc268a6..31f11affb2d 100644
--- a/src/app/pages/fund/components/fiat-provider-item.tsx
+++ b/src/app/pages/fund/components/fiat-provider-item.tsx
@@ -1,10 +1,10 @@
import { FundPageSelectors } from '@tests/selectors/fund.selectors';
import { AvailableRegions } from '@app/query/common/remote-config/remote-config.query';
+import { Tag } from '@app/ui/components/tag/tag';
+import { StarIcon, ZapIcon } from '@app/ui/icons';
-import { FastCheckoutBadge } from './fast-checkout-badge';
import { FundAccountTile } from './fund-account-tile';
-import { ZeroPercentFeesBadge } from './zero-percent-fees-badge';
const availableInsideUnitedStatesDescription = 'Available only inside of the US';
const availableOutsideUnitedStatesDescription = 'Available only outside of the US';
@@ -37,8 +37,12 @@ export function FiatProviderItem(props: FiatProviderProps) {
const Attributes = (
<>
- {hasFastCheckoutProcess && }
- {!hasTradingFees && }
+ {hasFastCheckoutProcess && (
+ } label="Fast checkout" variant="success" />
+ )}
+ {!hasTradingFees && (
+ } label="0 % Fees" variant="warning" />
+ )}
>
);
diff --git a/src/app/pages/fund/components/zero-percent-fees-badge.tsx b/src/app/pages/fund/components/zero-percent-fees-badge.tsx
deleted file mode 100644
index 9659155f7fa..00000000000
--- a/src/app/pages/fund/components/zero-percent-fees-badge.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { HStack, styled } from 'leather-styles/jsx';
-
-import { StarIcon } from '@app/ui/icons/star-icon';
-
-export function ZeroPercentFeesBadge() {
- return (
-
-
-
- 0 % Fees
-
-
- );
-}
diff --git a/src/app/ui/components/callout/callout.tsx b/src/app/ui/components/callout/callout.tsx
index 553c650fc1b..7ba98707b97 100644
--- a/src/app/ui/components/callout/callout.tsx
+++ b/src/app/ui/components/callout/callout.tsx
@@ -1,44 +1,51 @@
import type { ReactNode } from 'react';
-import { css } from 'leather-styles/css';
+import { type RecipeVariantProps, cva } from 'leather-styles/css';
import { Box, type BoxProps, Stack, styled } from 'leather-styles/jsx';
import { Flag } from '../flag/flag';
import { getIconVariant } from './callout.utils';
-type CalloutVariant = 'default' | 'error' | 'info' | 'success' | 'warning';
-
-const calloutStyles = css({
- color: 'ink.text-primary',
- textAlign: 'left',
- width: '100%',
-
- '&[data-variant="default"]': {
- backgroundColor: 'ink.non-interactive',
- },
- '&[data-variant="error"]': {
- backgroundColor: 'red.background-secondary',
+const calloutRecipe = cva({
+ base: {
+ color: 'ink.text-primary',
+ textAlign: 'left',
+ width: '100%',
},
- '&[data-variant="info"]': {
- backgroundColor: 'blue.background-secondary',
+ variants: {
+ variant: {
+ default: {
+ bg: 'ink.non-interactive',
+ },
+ error: {
+ bg: 'red.background-secondary',
+ },
+ info: {
+ bg: 'blue.background-secondary',
+ },
+ success: {
+ bg: 'green.background-secondary',
+ },
+ warning: {
+ bg: 'yellow.background-secondary',
+ },
+ },
},
- '&[data-variant="success"]': {
- backgroundColor: 'green.background-secondary',
- },
- '&[data-variant="warning"]': {
- backgroundColor: 'yellow.background-secondary',
+ defaultVariants: {
+ variant: 'default',
},
});
+type CalloutVariants = RecipeVariantProps;
+
interface CalloutProps extends BoxProps {
icon?: ReactNode;
title?: string;
- variant?: CalloutVariant;
}
-export function Callout(props: CalloutProps) {
+export function Callout(props: CalloutProps & CalloutVariants) {
const { children, icon, title, variant = 'default', ...rest } = props;
return (
-
+
+
+
+ );
+}
diff --git a/src/app/ui/components/tag/tag.stories.tsx b/src/app/ui/components/tag/tag.stories.tsx
new file mode 100644
index 00000000000..0a4444facc5
--- /dev/null
+++ b/src/app/ui/components/tag/tag.stories.tsx
@@ -0,0 +1,32 @@
+import type { Meta, StoryObj } from '@storybook/react';
+
+import { ErrorCircleIcon } from '@app/ui/icons';
+
+import { Tag as Component } from './tag';
+
+const meta: Meta = {
+ component: Component,
+ tags: ['autodocs'],
+ title: 'Tag',
+ parameters: {
+ controls: { include: ['transparent', 'variant'] },
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Tag: Story = {
+ args: {
+ label: 'Label',
+ variant: 'default',
+ },
+};
+
+export const WithIcon: Story = {
+ args: {
+ icon: ,
+ label: 'Label',
+ variant: 'default',
+ },
+};
diff --git a/src/app/ui/components/tag/tag.tsx b/src/app/ui/components/tag/tag.tsx
new file mode 100644
index 00000000000..39490283474
--- /dev/null
+++ b/src/app/ui/components/tag/tag.tsx
@@ -0,0 +1,64 @@
+import { type RecipeVariantProps, cva } from 'leather-styles/css';
+import { HStack, type HTMLStyledProps, styled } from 'leather-styles/jsx';
+
+const tagRecipe = cva({
+ base: {
+ borderRadius: 'xs',
+ fontWeight: 500,
+ maxWidth: 'fit-content',
+ maxHeight: 'fit-content',
+ p: 'space.01',
+ textStyle: 'label.03',
+ },
+ variants: {
+ variant: {
+ default: {
+ bg: 'ink.background-secondary',
+ border: '1px solid {colors.ink.border-transparent}',
+ color: 'ink.text-subdued',
+ },
+ error: {
+ bg: 'red.background-primary',
+ border: '1px solid {colors.red.border}',
+ color: 'red.action-primary-default',
+ },
+ info: {
+ bg: 'blue.background-primary',
+ border: '1px solid {colors.blue.border}',
+ color: 'blue.action-primary-default',
+ },
+ success: {
+ bg: 'green.background-primary',
+ border: '1px solid {colors.green.border}',
+ color: 'green.action-primary-default',
+ },
+ warning: {
+ bg: 'yellow.background-primary',
+ border: '1px solid {colors.yellow.border}',
+ color: 'yellow.action-primary-default',
+ },
+ },
+
+ transparent: { true: { bg: 'transparent' } },
+ },
+ defaultVariants: {
+ variant: 'default',
+ },
+});
+
+export type TagVariants = RecipeVariantProps;
+
+export interface TagProps extends HTMLStyledProps<'div'> {
+ icon?: React.JSX.Element;
+ label: string;
+}
+export function Tag({ icon, label, transparent, variant, ...props }: TagProps & TagVariants) {
+ return (
+
+
+ {icon && icon}
+ {label}
+
+
+ );
+}