@synerise/ds-badge 1.0.56 → 1.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/CLAUDE.md +138 -0
- package/README.md +21 -15
- package/dist/Badge.d.ts +9 -1
- package/dist/Badge.js +8 -8
- package/dist/Badge.styles.d.ts +20 -3
- package/dist/Badge.styles.js +53 -23
- package/dist/Badge.types.d.ts +52 -9
- package/dist/BadgeCore.d.ts +13 -0
- package/dist/BadgeCore.js +47 -0
- package/dist/BadgeWithLabel.d.ts +14 -0
- package/dist/BadgeWithLabel.js +15 -0
- package/dist/BadgeWithLabel.styles.d.ts +2 -0
- package/dist/BadgeWithLabel.styles.js +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +6 -5
- package/dist/assets/style/index-tn0RQdqM.css +0 -0
- package/dist/style/index.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.0.58](https://github.com/Synerise/synerise-design/compare/@synerise/ds-badge@1.0.57...@synerise/ds-badge@1.0.58) (2026-07-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @synerise/ds-badge
|
|
9
|
+
|
|
10
|
+
## [1.0.57](https://github.com/Synerise/synerise-design/compare/@synerise/ds-badge@1.0.56...@synerise/ds-badge@1.0.57) (2026-06-17)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @synerise/ds-badge
|
|
13
|
+
|
|
6
14
|
## [1.0.56](https://github.com/Synerise/synerise-design/compare/@synerise/ds-badge@1.0.55...@synerise/ds-badge@1.0.56) (2026-06-11)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @synerise/ds-badge
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Badge (`@synerise/ds-badge`)
|
|
2
|
+
|
|
3
|
+
> DS-native badge (status dot, flag/pulsing dot, count badge). **antd-free** — exposes `ds-badge*`
|
|
4
|
+
> DOM/class hooks so downstream styled-overrides (e.g. ds-avatar) keep working. The legacy
|
|
5
|
+
> `ant-badge*` hooks have been dropped (so a parent app on the old antd-based badge can't leak its
|
|
6
|
+
> global `.ant-badge*` styles onto this one). Colour is driven by `status` (or `customColor`); there
|
|
7
|
+
> is no antd dependency.
|
|
8
|
+
|
|
9
|
+
## Package structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
src/
|
|
13
|
+
Badge.tsx — public entry: `text` → BadgeWithLabel, otherwise BadgeCore
|
|
14
|
+
BadgeCore.tsx — dot/count renderer (derives dot/count mode, renders the styled-components tree)
|
|
15
|
+
Badge.styles.tsx — styled-components (Wrapper, CountSup, ScrollNumberOnly, Current, DotSup, CustomCountSup) + colour helpers
|
|
16
|
+
Badge.types.ts — BadgeProps, Color, ColorHue, Status
|
|
17
|
+
BadgeWithLabel.tsx — status dot aligned next to a text label (powers the `text` prop; also exported)
|
|
18
|
+
BadgeWithLabel.styles.ts — inline-flex alignment for dot↔label
|
|
19
|
+
Badge.figma.tsx — Code Connect mappings (status-driven)
|
|
20
|
+
index.ts — public exports
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> No `style/` LESS folder — the antd badge LESS base was inlined into `Badge.styles.tsx`. Styling uses
|
|
24
|
+
> first-class styled-components with transient `$`-props; the elements carry `ds-badge-*` class names
|
|
25
|
+
> (for DS consumers / ui-tests / external CSS) but they are not used as styling selectors.
|
|
26
|
+
|
|
27
|
+
## Public exports
|
|
28
|
+
|
|
29
|
+
### `Badge` (default)
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Description |
|
|
32
|
+
|------|------|---------|-------------|
|
|
33
|
+
| `status` | `BadgeStatus` | `undefined` | DS status — drives the dot/count colour: `active`→green-600, `inactive`→grey-400, `blocked`→red-600, `processing`→blue-600, `warning`→yellow-600. Auto-enables dot mode. |
|
|
34
|
+
| `flag` | `boolean` | `undefined` | Renders the dot with `::before`/`::after` halos. Requires dot/status. |
|
|
35
|
+
| `pulsing` | `boolean` | `undefined` | Pulse animation on the halos. Only visible when `flag` or `status` is set. |
|
|
36
|
+
| `outlined` | `boolean` | `undefined` | White `box-shadow` ring around the count badge. |
|
|
37
|
+
| `customColor` | `LiteralStringUnion<BadgeColor \| DefaultColor>` | `undefined` | Overrides the badge colour. Palette token → resolved via `theme.palette` (`'blue'` → `blue-600`, or full key `'blue-600'`); any other value is used as a **raw CSS colour** (`'#FF0000'`, `'rgb(…)'`, …), so colours outside the palette work. |
|
|
38
|
+
| `count` | `ReactNode` | `undefined` | Number/node in the count badge. Hidden when `0`. |
|
|
39
|
+
| `dot` | `boolean` | `undefined` | Forces dot mode (auto-enabled by `status`). |
|
|
40
|
+
| `overflowCount` | `number` | `99` | Max number before `N+`. |
|
|
41
|
+
| `offset` | `[number\|string, number\|string]` | `undefined` | `[x, y]` offset of the badge relative to its children. |
|
|
42
|
+
| `children` | `ReactNode` | `undefined` | When omitted, the badge renders inline (standalone). |
|
|
43
|
+
| `text` | `ReactNode` | `undefined` | When set, renders a status/dot badge next to this label (delegates to `BadgeWithLabel`) — the legacy antd `status` + `text` API. Takes precedence over `count`/`children`; only `status`/`customColor`/`flag`/`pulsing`/`dot`/`className`/`style` apply in this mode. |
|
|
44
|
+
| `className`, `style` | — | — | Applied to the outer wrapper. |
|
|
45
|
+
| `data-*`, `aria-*` | — | — | Forwarded to the outermost wrapper (`PassthroughAttributes` from `@synerise/ds-utils`). |
|
|
46
|
+
|
|
47
|
+
### `BadgeWithLabel` (named export)
|
|
48
|
+
|
|
49
|
+
A status/dot `Badge` aligned next to a text label. Owns the dot↔label alignment (inline-flex, 8px
|
|
50
|
+
gap) so consumers don't carry that CSS. It powers the `Badge` `text` prop and is also exported for
|
|
51
|
+
direct use.
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Description |
|
|
54
|
+
|------|------|-------------|
|
|
55
|
+
| `status` / `customColor` / `flag` / `pulsing` / `dot` | — | Forwarded to the inner `Badge`. |
|
|
56
|
+
| `children` | `ReactNode` | The label rendered next to the dot. |
|
|
57
|
+
| `className`, `style` | — | Applied to the wrapper. |
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { BadgeWithLabel } from '@synerise/ds-badge';
|
|
61
|
+
<BadgeWithLabel status="warning">Needs review</BadgeWithLabel>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Types
|
|
65
|
+
|
|
66
|
+
| Export | Description |
|
|
67
|
+
|--------|-------------|
|
|
68
|
+
| `BadgeProps` | Full props type (`BadgeOwnProps & PassthroughAttributes`) |
|
|
69
|
+
| `BadgeWithLabelProps` | Props for `BadgeWithLabel` |
|
|
70
|
+
| `BadgeStatus` | `'active' \| 'inactive' \| 'blocked' \| 'processing' \| 'warning' \| undefined` |
|
|
71
|
+
| `BadgeColor` | `'red' \| 'green' \| 'grey' \| 'yellow' \| 'blue' \| 'pink' \| 'mars' \| 'orange' \| 'fern' \| 'cyan' \| 'purple' \| 'violet' \| 'white' \| 'transparent'` |
|
|
72
|
+
| `BadgeColorHue` | `'900' \| '800' \| '700' \| '600' \| '500' \| '400' \| '300' \| '200' \| '100' \| '050'` |
|
|
73
|
+
|
|
74
|
+
## Usage patterns
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import Badge from '@synerise/ds-badge';
|
|
78
|
+
|
|
79
|
+
// Count badge (red by default; colour with status/customColor, or override via `style`)
|
|
80
|
+
<Badge count={5}><Avatar /></Badge>
|
|
81
|
+
<Badge count={3} status="blocked" />
|
|
82
|
+
<Badge count={3} customColor="blue" />
|
|
83
|
+
|
|
84
|
+
// Status dot (dot auto-enabled by status).
|
|
85
|
+
<Badge status="active" />
|
|
86
|
+
|
|
87
|
+
// Status dot + label — pass `text` (legacy API) or use BadgeWithLabel directly.
|
|
88
|
+
<Badge status="active" text="Online" />
|
|
89
|
+
|
|
90
|
+
// Flag dot with pulse
|
|
91
|
+
<Badge status="processing" flag pulsing><Avatar /></Badge>
|
|
92
|
+
|
|
93
|
+
// Custom dot colour (arbitrary, non-status colour)
|
|
94
|
+
<Badge status="active" customColor="purple-700" />
|
|
95
|
+
|
|
96
|
+
// data-* passthrough on the wrapper
|
|
97
|
+
<Badge status="active" data-testid="presence" />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Styling
|
|
101
|
+
|
|
102
|
+
`Badge.styles.tsx` is `styled(BadgeBase)`. It **inlines the base badge CSS** that antd's LESS used to
|
|
103
|
+
provide (wrapper positioning, count pill, dot, `.ds-badge-not-a-wrapper` standalone layout) and adds
|
|
104
|
+
the DS overrides. DS-only styling props (`flag`, `pulsing`, `outlined`, `customColor`) are stripped in
|
|
105
|
+
the wrapper before reaching `BadgeBase`'s DOM; they are still read by the CSS interpolations.
|
|
106
|
+
|
|
107
|
+
Colours come from `@synerise/ds-core` theme palette tokens (`resolveColor`): `customColor` → `status`
|
|
108
|
+
colour → **red** default (count text is white). Consumers wanting a different look (e.g. a neutral
|
|
109
|
+
count chip) override it with an inline `style`/`styled(Badge)` — and, matching antd, the consumer's
|
|
110
|
+
`style` is applied to the **indicator element** (count/dot), not the wrapper, so
|
|
111
|
+
`style={{ backgroundColor: 'transparent', color: ... }}` recolours the count (e.g. the Tabs counter).
|
|
112
|
+
A custom-node `count` (e.g. an icon) renders bare via `.ds-badge-scroll-number-custom-component` — no pill
|
|
113
|
+
background. Count badge is 16px tall; count text uses `macro.h200` from `@synerise/ds-typography`. The
|
|
114
|
+
theme type is `ThemeProps` from `@synerise/ds-core` (not styled-components' `DefaultTheme`, unaugmented here).
|
|
115
|
+
|
|
116
|
+
## Key dependencies
|
|
117
|
+
|
|
118
|
+
- `@synerise/ds-core` — theme palette tokens, `ThemeProps`, `DefaultColor`
|
|
119
|
+
- `@synerise/ds-typography` — `macro.h200` for count text
|
|
120
|
+
- `@synerise/ds-utils` — `PassthroughAttributes` (data-*/aria-* type)
|
|
121
|
+
|
|
122
|
+
## Implementation notes
|
|
123
|
+
|
|
124
|
+
- **No antd.** `BadgeBase` renders the DOM with `ds-badge` / `ds-badge-count` / `ds-badge-dot` /
|
|
125
|
+
`ds-badge-status-dot` / `ds-badge-status-<status>` class hooks, which the DS consumers' selectors
|
|
126
|
+
target (e.g. ds-avatar's `& ~ .ds-badge-dot`). The dot `sup` carries `ds-badge-dot` **and**
|
|
127
|
+
`ds-badge-status-dot ds-badge-status-<status>` when `status` is set. The legacy `ant-badge-*` /
|
|
128
|
+
`ant-scroll-number-*` hooks were removed so a parent app still on the old antd-based badge can't
|
|
129
|
+
leak its global `.ant-badge*` styles onto the new one.
|
|
130
|
+
- **Colour is status-driven.** The old `backgroundColor` / `backgroundColorHue` / `textColor` /
|
|
131
|
+
`textColorHue` props and the antd-passthrough `color` / `text` props were **removed**; `showZero` /
|
|
132
|
+
`size` / `title` / `id` and the antd `Omit<AntBadgeProps>` inheritance are gone too. `customColor`
|
|
133
|
+
is kept for arbitrary per-item colours (segment lists, status-label table cells).
|
|
134
|
+
- **`dot` is auto-derived from `status`** — set `status` and you get a dot without `dot={true}`.
|
|
135
|
+
- **Standalone vs wrapping** — with no `children` the wrapper gets `ds-badge-not-a-wrapper` and the
|
|
136
|
+
badge renders inline (no absolute positioning / offset).
|
|
137
|
+
- **`text` restored** — when `text` is set, `Badge` delegates to `BadgeWithLabel` (status dot + label), so the legacy `status` + `text` API keeps working without switching components; `BadgeWithLabel` is still exported for direct use. To avoid a `Badge ↔ BadgeWithLabel` import cycle, the dot/count renderer lives in `BadgeCore.tsx` — both `Badge` (text mode) and `BadgeWithLabel` render `BadgeCore`.
|
|
138
|
+
- Tests: Vitest (`src/__specs__/Badge.spec.tsx`).
|
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ import Badge from '@synerise/ds-badge'
|
|
|
42
42
|
<Badge
|
|
43
43
|
count={10}
|
|
44
44
|
overflowCount={11}
|
|
45
|
-
|
|
45
|
+
status="processing"
|
|
46
46
|
/>
|
|
47
47
|
|
|
48
48
|
```
|
|
@@ -71,22 +71,28 @@ import Badge from '@synerise/ds-badge'
|
|
|
71
71
|
|
|
72
72
|
| Property | Description | Type | Default |
|
|
73
73
|
| ------------------ | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | ------- |
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
| outlined | Add outline to the badge counter | boolean | `false` |
|
|
74
|
+
| status | Status that drives the dot/count colour | `active` / `inactive` / `blocked` / `processing` / `warning` | - |
|
|
75
|
+
| customColor | Override the badge colour — palette token or any raw CSS colour | `BadgeColor` / `DefaultColor` / CSS colour (e.g. `'blue-600'`, `'#FF0000'`) | - |
|
|
76
|
+
| count | Number to show in the badge counter (hidden when `0`) | ReactNode | - |
|
|
77
|
+
| dot | Display a dot instead of a counter (auto-enabled by `status`) | boolean | `false` |
|
|
78
|
+
| flag | Show the badge as a flag (halo rings) | boolean | `false` |
|
|
79
|
+
| offset | The offset of the badge in [x, y] format | [number, number] | - |
|
|
80
|
+
| outlined | Add a white outline to the badge counter | boolean | `false` |
|
|
82
81
|
| overflowCount | Maximum number to show in the counter | number | 99 |
|
|
83
82
|
| pulsing | Enable pulsing animation | boolean | `false` |
|
|
84
|
-
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
| data-\* / aria-\* | Forwarded to the outermost wrapper element | string / number / boolean | - |
|
|
84
|
+
|
|
85
|
+
> **Removed in the antd-free version:** `backgroundColor`, `backgroundColorHue`, `textColor`, `textColorHue` (count colour is now driven by `status`), `text` (use the `BadgeWithLabel` export instead), `showZero`, `title`. The component no longer extends antd's Badge props.
|
|
86
|
+
|
|
87
|
+
### `BadgeWithLabel`
|
|
88
|
+
|
|
89
|
+
A status dot aligned next to a text label — the replacement for the old `text` prop. Owns the dot↔label alignment so consumers don't.
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
import { BadgeWithLabel } from '@synerise/ds-badge'
|
|
93
|
+
|
|
94
|
+
<BadgeWithLabel status="warning">Needs review</BadgeWithLabel>
|
|
95
|
+
```
|
|
90
96
|
|
|
91
97
|
### Color
|
|
92
98
|
|
package/dist/Badge.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { BadgeProps } from './Badge.types';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Public Badge.
|
|
5
|
+
*
|
|
6
|
+
* When `text` is provided the badge renders as a status/dot badge aligned next to that label —
|
|
7
|
+
* delegating to `BadgeWithLabel` (this restores the legacy antd `status` + `text` API so consumers
|
|
8
|
+
* don't have to switch to `BadgeWithLabel` by hand). Otherwise it renders the dot/count badge
|
|
9
|
+
* (`BadgeCore`).
|
|
10
|
+
*/
|
|
11
|
+
declare const Badge: ({ text, ...props }: BadgeProps) => React.JSX.Element;
|
|
4
12
|
export default Badge;
|
package/dist/Badge.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import "./
|
|
2
|
+
import BadgeCore from "./BadgeCore.js";
|
|
3
|
+
import BadgeWithLabel from "./BadgeWithLabel.js";
|
|
4
4
|
const Badge = ({
|
|
5
|
-
|
|
5
|
+
text,
|
|
6
6
|
...props
|
|
7
7
|
}) => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return /* @__PURE__ */ jsx(
|
|
8
|
+
const hasText = text !== void 0 && text !== null && text !== false && text !== "";
|
|
9
|
+
if (hasText) {
|
|
10
|
+
return /* @__PURE__ */ jsx(BadgeWithLabel, { status: props.status, customColor: props.customColor, flag: props.flag, pulsing: props.pulsing, dot: props.dot, className: props.className, style: props.style, children: text });
|
|
11
|
+
}
|
|
12
|
+
return /* @__PURE__ */ jsx(BadgeCore, { ...props });
|
|
13
13
|
};
|
|
14
14
|
export {
|
|
15
15
|
Badge as default
|
package/dist/Badge.styles.d.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Status } from './Badge.types';
|
|
2
|
+
type ColorProps = {
|
|
3
|
+
$status?: Status;
|
|
4
|
+
$customColor?: string;
|
|
5
|
+
};
|
|
6
|
+
type PositionProps = {
|
|
7
|
+
$standalone?: boolean;
|
|
8
|
+
};
|
|
2
9
|
export declare const afterElementAnimation: import('styled-components').Keyframes;
|
|
3
10
|
export declare const beforeElementAnimation: import('styled-components').Keyframes;
|
|
4
|
-
declare const
|
|
5
|
-
export
|
|
11
|
+
export declare const Wrapper: import('styled-components').StyledComponent<"span", any, {}, never>;
|
|
12
|
+
export declare const CountSup: import('styled-components').StyledComponent<"sup", any, ColorProps & PositionProps & {
|
|
13
|
+
$outlined?: boolean;
|
|
14
|
+
}, never>;
|
|
15
|
+
export declare const ScrollNumberOnly: import('styled-components').StyledComponent<"span", any, {}, never>;
|
|
16
|
+
export declare const Current: import('styled-components').StyledComponent<"span", any, {}, never>;
|
|
17
|
+
export declare const CustomCountSup: import('styled-components').StyledComponent<"sup", any, PositionProps, never>;
|
|
18
|
+
export declare const DotSup: import('styled-components').StyledComponent<"sup", any, ColorProps & PositionProps & {
|
|
19
|
+
$flag?: boolean;
|
|
20
|
+
$pulsing?: boolean;
|
|
21
|
+
}, never>;
|
|
22
|
+
export {};
|
package/dist/Badge.styles.js
CHANGED
|
@@ -1,34 +1,64 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Badge } from "antd";
|
|
3
1
|
import styled, { css, keyframes } from "styled-components";
|
|
4
2
|
import { macro } from "@synerise/ds-typography";
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
const STATUS_COLOR_TOKEN = {
|
|
4
|
+
active: "green-600",
|
|
5
|
+
inactive: "grey-400",
|
|
6
|
+
blocked: "red-600",
|
|
7
|
+
processing: "blue-600",
|
|
8
|
+
warning: "yellow-600"
|
|
9
|
+
};
|
|
10
|
+
const resolveCustomColor = (theme, customColor) => {
|
|
11
|
+
const paletteColor = customColor.indexOf("-") >= 0 ? theme.palette[customColor] : theme.palette[`${customColor}-600`];
|
|
12
|
+
return paletteColor ?? customColor;
|
|
13
|
+
};
|
|
14
|
+
const resolveColor = (props) => {
|
|
15
|
+
const {
|
|
16
|
+
theme,
|
|
17
|
+
$customColor,
|
|
18
|
+
$status
|
|
19
|
+
} = props;
|
|
20
|
+
if ($customColor) {
|
|
21
|
+
return resolveCustomColor(theme, $customColor);
|
|
8
22
|
}
|
|
9
|
-
if (
|
|
10
|
-
return
|
|
23
|
+
if ($status) {
|
|
24
|
+
return theme.palette[STATUS_COLOR_TOKEN[$status]];
|
|
11
25
|
}
|
|
12
|
-
return
|
|
26
|
+
return theme.palette["red-600"];
|
|
13
27
|
};
|
|
28
|
+
const indicatorPosition = (standalone) => standalone ? css(["position:relative;top:auto;right:auto;display:inline-block;vertical-align:middle;transform:none;"]) : css(["position:absolute;top:0;right:0;transform:translate(50%,-50%);transform-origin:100% 0%;"]);
|
|
14
29
|
const afterElementAnimation = /* @__PURE__ */ keyframes(["0%{transform:translate3d(-5px,-5px,0) scale(0.3);opacity:0.9;}100%{transform:translate3d(-5px,-5px,0) scale(1.5);opacity:0;}"]);
|
|
15
30
|
const beforeElementAnimation = /* @__PURE__ */ keyframes(["0%{transform:translate3d(-2px,-2px,0) scale(0.5);opacity:0.9;}100%{transform:translate3d(-2px,-2px,0) scale(1.5);opacity:0;}"]);
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
outlined,
|
|
19
|
-
backgroundColor,
|
|
20
|
-
textColor,
|
|
21
|
-
backgroundColorHue,
|
|
22
|
-
textColorHue,
|
|
23
|
-
pulsing,
|
|
24
|
-
customColor,
|
|
25
|
-
...rest
|
|
26
|
-
}) => /* @__PURE__ */ jsx(Badge, { ...rest })).withConfig({
|
|
27
|
-
displayName: "Badgestyles",
|
|
31
|
+
const Wrapper = /* @__PURE__ */ styled.span.withConfig({
|
|
32
|
+
displayName: "Badgestyles__Wrapper",
|
|
28
33
|
componentId: "sc-1ci72bj-0"
|
|
29
|
-
})(["
|
|
34
|
+
})(["position:relative;display:inline-block;line-height:1;"]);
|
|
35
|
+
const CountSup = /* @__PURE__ */ styled.sup.withConfig({
|
|
36
|
+
displayName: "Badgestyles__CountSup",
|
|
37
|
+
componentId: "sc-1ci72bj-1"
|
|
38
|
+
})(["z-index:auto;", ";min-width:16px;height:16px;padding:0 3px;white-space:nowrap;text-align:center;border-radius:8px;background-color:", ";color:", ";box-shadow:", ";"], (props) => indicatorPosition(props.$standalone), (props) => resolveColor(props), (props) => props.theme.palette.white, (props) => props.$outlined ? `0 0 0 1px ${props.theme.palette.white}` : "none");
|
|
39
|
+
const ScrollNumberOnly = /* @__PURE__ */ styled.span.withConfig({
|
|
40
|
+
displayName: "Badgestyles__ScrollNumberOnly",
|
|
41
|
+
componentId: "sc-1ci72bj-2"
|
|
42
|
+
})(["display:inline-block;height:16px;"]);
|
|
43
|
+
const Current = /* @__PURE__ */ styled.span.withConfig({
|
|
44
|
+
displayName: "Badgestyles__Current",
|
|
45
|
+
componentId: "sc-1ci72bj-3"
|
|
46
|
+
})(["", ";height:16px;line-height:16px;font-weight:400;color:inherit;"], macro.h200);
|
|
47
|
+
const CustomCountSup = /* @__PURE__ */ styled.sup.withConfig({
|
|
48
|
+
displayName: "Badgestyles__CustomCountSup",
|
|
49
|
+
componentId: "sc-1ci72bj-4"
|
|
50
|
+
})(["z-index:auto;", ";"], (props) => indicatorPosition(props.$standalone));
|
|
51
|
+
const DotSup = /* @__PURE__ */ styled.sup.withConfig({
|
|
52
|
+
displayName: "Badgestyles__DotSup",
|
|
53
|
+
componentId: "sc-1ci72bj-5"
|
|
54
|
+
})(["z-index:auto;", ";width:6px;height:6px;border-radius:50%;background-color:", ";", ""], (props) => indicatorPosition(props.$standalone), (props) => resolveColor(props), (props) => (!!props.$flag || !!props.$status) && css(["box-sizing:border-box;width:10px;height:10px;overflow:visible;border:2px solid ", ";box-shadow:none;&::before{display:", ";content:", ";transform:translate3d(-2px,-2px,0);transform-origin:center;", "}&::after{display:", ";content:", ";transform:translate3d(-5px,-5px,0);transform-origin:center;", "}"], props.theme.palette.white, props.$flag ? "flex" : "none", props.$flag ? "''" : "none", props.$pulsing && css(["position:absolute;top:0;left:0;width:10px;height:10px;background-color:inherit;border-radius:50%;animation:", " 2s infinite;"], beforeElementAnimation), props.$flag ? "flex" : "none", props.$flag ? "''" : "none", props.$pulsing && css(["position:absolute;top:0;left:0;width:16px;height:16px;background-color:inherit;border-radius:50%;animation:", " 2s infinite;"], afterElementAnimation)));
|
|
30
55
|
export {
|
|
56
|
+
CountSup,
|
|
57
|
+
Current,
|
|
58
|
+
CustomCountSup,
|
|
59
|
+
DotSup,
|
|
60
|
+
ScrollNumberOnly,
|
|
61
|
+
Wrapper,
|
|
31
62
|
afterElementAnimation,
|
|
32
|
-
beforeElementAnimation
|
|
33
|
-
StyledBadge as default
|
|
63
|
+
beforeElementAnimation
|
|
34
64
|
};
|
package/dist/Badge.types.d.ts
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { DefaultColor } from '@synerise/ds-core';
|
|
3
|
+
import { LiteralStringUnion, PassthroughAttributes } from '@synerise/ds-utils';
|
|
3
4
|
export declare const color: readonly ["red", "green", "grey", "yellow", "blue", "pink", "mars", "orange", "fern", "cyan", "purple", "violet", "white", "transparent"];
|
|
4
5
|
export type Color = (typeof color)[number];
|
|
5
6
|
export type ColorHue = '900' | '800' | '700' | '600' | '500' | '400' | '300' | '200' | '100' | '050';
|
|
6
7
|
export type Status = 'active' | 'inactive' | 'blocked' | 'processing' | 'warning' | undefined;
|
|
7
|
-
export type
|
|
8
|
-
|
|
8
|
+
export type BadgeOwnProps = {
|
|
9
|
+
/**
|
|
10
|
+
* Content the badge is positioned over. When omitted, the badge renders inline (standalone).
|
|
11
|
+
*/
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* When set, the badge renders as a status/dot badge aligned next to this label (delegating to
|
|
15
|
+
* `BadgeWithLabel`). Restores the legacy antd `status` + `text` API. Takes precedence over
|
|
16
|
+
* `count` / `children` — only `status`, `customColor`, `flag`, `pulsing`, `dot`, `className` and
|
|
17
|
+
* `style` apply in this mode.
|
|
18
|
+
*/
|
|
19
|
+
text?: ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* DS status — drives the dot / count colour.
|
|
22
|
+
*/
|
|
9
23
|
status?: Status;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Renders the dot with `::before`/`::after` halo rings. Requires dot/status to be active.
|
|
26
|
+
*/
|
|
27
|
+
flag?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Adds a repeating pulse animation to the halo rings. Only visible when `flag` or `status` is set.
|
|
30
|
+
*/
|
|
15
31
|
pulsing?: boolean;
|
|
16
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Adds a white outline ring around the count badge.
|
|
34
|
+
*/
|
|
35
|
+
outlined?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Overrides the badge colour. Accepts a palette token (`'blue'` → `blue-600`, or a full key like
|
|
38
|
+
* `'blue-600'`), or any raw CSS colour (`'#FF0000'`, `'rgb(…)'`, …) for colours outside the palette.
|
|
39
|
+
*/
|
|
40
|
+
customColor?: LiteralStringUnion<Color | DefaultColor>;
|
|
41
|
+
/**
|
|
42
|
+
* Number (or node) shown inside the count badge.
|
|
43
|
+
*/
|
|
44
|
+
count?: ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Forces dot mode. Auto-enabled when `status` is provided.
|
|
47
|
+
*/
|
|
48
|
+
dot?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Maximum number before the count is shown as `N+`.
|
|
51
|
+
*/
|
|
52
|
+
overflowCount?: number;
|
|
53
|
+
/**
|
|
54
|
+
* `[x, y]` pixel offset of the badge relative to its children.
|
|
55
|
+
*/
|
|
56
|
+
offset?: [number | string, number | string];
|
|
57
|
+
className?: string;
|
|
58
|
+
style?: CSSProperties;
|
|
17
59
|
};
|
|
60
|
+
export type BadgeProps = BadgeOwnProps & PassthroughAttributes;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { BadgeProps } from './Badge.types';
|
|
3
|
+
/**
|
|
4
|
+
* DS-native, antd-free badge core (status dot / count). Renders DS styled-components (no styling via
|
|
5
|
+
* class selectors). Each element carries `ds-badge-*` class hooks for DS consumers (avatar, tabs,
|
|
6
|
+
* tag, …), external CSS and ui-tests. The legacy `ant-badge-*` / `ant-scroll-number-*` hooks have
|
|
7
|
+
* been dropped so a parent app still on the old antd-based badge can no longer leak its global
|
|
8
|
+
* `.ant-badge*` styles onto this one.
|
|
9
|
+
*
|
|
10
|
+
* Public entry is `./Badge` — it delegates here, or to `BadgeWithLabel` when `text` is set.
|
|
11
|
+
*/
|
|
12
|
+
declare const BadgeCore: ({ children, status, count, dot, flag, pulsing, outlined, customColor, overflowCount, offset, className, style, ...passthrough }: BadgeProps) => React.JSX.Element;
|
|
13
|
+
export default BadgeCore;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Wrapper, CustomCountSup, CountSup, ScrollNumberOnly, Current, DotSup } from "./Badge.styles.js";
|
|
4
|
+
const DEFAULT_OVERFLOW_COUNT = 99;
|
|
5
|
+
const toOffsetUnit = (value) => typeof value === "number" ? `${value}px` : value;
|
|
6
|
+
const renderCount = (count, overflowCount) => {
|
|
7
|
+
if (typeof count === "number" && count > overflowCount) {
|
|
8
|
+
return `${overflowCount}+`;
|
|
9
|
+
}
|
|
10
|
+
return count;
|
|
11
|
+
};
|
|
12
|
+
const BadgeCore = ({
|
|
13
|
+
children,
|
|
14
|
+
status,
|
|
15
|
+
count,
|
|
16
|
+
dot,
|
|
17
|
+
flag,
|
|
18
|
+
pulsing,
|
|
19
|
+
outlined,
|
|
20
|
+
customColor,
|
|
21
|
+
overflowCount = DEFAULT_OVERFLOW_COUNT,
|
|
22
|
+
offset,
|
|
23
|
+
className,
|
|
24
|
+
style,
|
|
25
|
+
...passthrough
|
|
26
|
+
}) => {
|
|
27
|
+
const hasCount = count !== void 0 && count !== null && count !== false && count !== 0 && count !== "0";
|
|
28
|
+
const isDot = dot !== void 0 ? dot : status !== void 0 && !hasCount;
|
|
29
|
+
const hasChildren = children !== void 0 && children !== null && children !== false;
|
|
30
|
+
const standalone = !hasChildren;
|
|
31
|
+
const showCount = !isDot && hasCount;
|
|
32
|
+
const isCustomCount = React.isValidElement(count);
|
|
33
|
+
const wrapperClassName = ["ds-badge", standalone && "ds-badge-not-a-wrapper", className].filter(Boolean).join(" ");
|
|
34
|
+
const indicatorStyle = offset && hasChildren ? {
|
|
35
|
+
transform: `translate(calc(50% + ${toOffsetUnit(offset[0])}), calc(-50% + ${toOffsetUnit(offset[1])}))`,
|
|
36
|
+
...style
|
|
37
|
+
} : style;
|
|
38
|
+
const statusClassName = status ? ` ds-badge-status-dot ds-badge-status-${status}` : "";
|
|
39
|
+
return /* @__PURE__ */ jsxs(Wrapper, { className: wrapperClassName, ...passthrough, children: [
|
|
40
|
+
children,
|
|
41
|
+
showCount && (isCustomCount ? /* @__PURE__ */ jsx(CustomCountSup, { className: "ds-badge-scroll-number-custom-component", $standalone: standalone, style: indicatorStyle, children: count }) : /* @__PURE__ */ jsx(CountSup, { className: "ds-badge-scroll-number ds-badge-count", $standalone: standalone, $status: status, $customColor: customColor, $outlined: outlined, title: typeof count === "string" || typeof count === "number" ? String(count) : void 0, style: indicatorStyle, children: /* @__PURE__ */ jsx(ScrollNumberOnly, { className: "ds-badge-scroll-number-only", children: /* @__PURE__ */ jsx(Current, { className: "current", children: renderCount(count, overflowCount) }) }) })),
|
|
42
|
+
isDot && /* @__PURE__ */ jsx(DotSup, { className: `ds-badge-dot${statusClassName}`, $standalone: standalone, $status: status, $customColor: customColor, $flag: flag, $pulsing: pulsing, style: indicatorStyle })
|
|
43
|
+
] });
|
|
44
|
+
};
|
|
45
|
+
export {
|
|
46
|
+
BadgeCore as default
|
|
47
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { default as React, CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import { BadgeProps } from './Badge.types';
|
|
3
|
+
export type BadgeWithLabelProps = Pick<BadgeProps, 'status' | 'customColor' | 'flag' | 'pulsing' | 'dot'> & {
|
|
4
|
+
/** Label rendered next to the badge dot. */
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: CSSProperties;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A status/dot `Badge` aligned next to a text label — the antd-free replacement for the old
|
|
11
|
+
* `Badge` `text` prop. Owns the dot↔label alignment so consumers don't have to.
|
|
12
|
+
*/
|
|
13
|
+
declare const BadgeWithLabel: ({ children, className, style, ...badgeProps }: BadgeWithLabelProps) => React.JSX.Element;
|
|
14
|
+
export default BadgeWithLabel;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import BadgeCore from "./BadgeCore.js";
|
|
3
|
+
import { Wrapper, Label } from "./BadgeWithLabel.styles.js";
|
|
4
|
+
const BadgeWithLabel = ({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
style,
|
|
8
|
+
...badgeProps
|
|
9
|
+
}) => /* @__PURE__ */ jsxs(Wrapper, { className, style, children: [
|
|
10
|
+
/* @__PURE__ */ jsx(BadgeCore, { ...badgeProps }),
|
|
11
|
+
/* @__PURE__ */ jsx(Label, { children })
|
|
12
|
+
] });
|
|
13
|
+
export {
|
|
14
|
+
BadgeWithLabel as default
|
|
15
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
const Wrapper = /* @__PURE__ */ styled.span.withConfig({
|
|
3
|
+
displayName: "BadgeWithLabelstyles__Wrapper",
|
|
4
|
+
componentId: "sc-14o8m20-0"
|
|
5
|
+
})(["display:inline-flex;align-items:center;gap:8px;"]);
|
|
6
|
+
const Label = /* @__PURE__ */ styled.span.withConfig({
|
|
7
|
+
displayName: "BadgeWithLabelstyles__Label",
|
|
8
|
+
componentId: "sc-14o8m20-1"
|
|
9
|
+
})(["line-height:1;color:", ";"], (props) => props.theme.palette["grey-600"]);
|
|
10
|
+
export {
|
|
11
|
+
Label,
|
|
12
|
+
Wrapper
|
|
13
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-badge",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.58",
|
|
4
4
|
"description": "Badge UI Component for the Synerise Design System",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": "Synerise/synerise-design",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"/dist",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
+
"CLAUDE.md",
|
|
20
21
|
"README.md",
|
|
21
22
|
"package.json",
|
|
22
23
|
"LICENSE.md"
|
|
@@ -41,15 +42,15 @@
|
|
|
41
42
|
],
|
|
42
43
|
"types": "dist/index.d.ts",
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@synerise/ds-icon": "^1.18.
|
|
45
|
-
"@synerise/ds-typography": "^1.1.
|
|
45
|
+
"@synerise/ds-icon": "^1.18.5",
|
|
46
|
+
"@synerise/ds-typography": "^1.1.27",
|
|
47
|
+
"@synerise/ds-utils": "^1.10.2"
|
|
46
48
|
},
|
|
47
49
|
"peerDependencies": {
|
|
48
50
|
"@synerise/ds-core": "*",
|
|
49
|
-
"antd": "4.24.16",
|
|
50
51
|
"react": ">=16.9.0 <= 18.3.1",
|
|
51
52
|
"styled-components": "^5.3.3",
|
|
52
53
|
"vitest": "4"
|
|
53
54
|
},
|
|
54
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "d0a43cc43d8528a36f105aceea52ab470edb71d9"
|
|
55
56
|
}
|
|
File without changes
|
package/dist/style/index.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.ant-badge{box-sizing:border-box;margin:0;padding:0;color:#6a7580;font-size:13px;font-variant:tabular-nums;line-height:1.38;list-style:none;font-feature-settings:'tnum';position:relative;display:inline-block;line-height:1}.ant-badge-count{z-index:auto;min-width:20px;height:20px;padding:0 6px;color:#fff;font-weight:400;font-size:11px;line-height:20px;white-space:nowrap;text-align:center;background:#ff4d4f;border-radius:10px;box-shadow:0 0 0 1px #fff}.ant-badge-count a,.ant-badge-count a:hover{color:#fff}.ant-badge-count-sm{min-width:14px;height:14px;padding:0;font-size:11px;line-height:14px;border-radius:7px}.ant-badge-multiple-words{padding:0 8px}.ant-badge-dot{z-index:auto;width:6px;min-width:6px;height:6px;background:#ff4d4f;border-radius:100%;box-shadow:0 0 0 1px #fff}.ant-badge-dot.ant-scroll-number{transition:background 1.5s}.ant-badge .ant-scroll-number-custom-component,.ant-badge-count,.ant-badge-dot{position:absolute;top:0;right:0;transform:translate(50%,-50%);transform-origin:100% 0%}.ant-badge .ant-scroll-number-custom-component.anticon-spin,.ant-badge-count.anticon-spin,.ant-badge-dot.anticon-spin{animation:antBadgeLoadingCircle 1s infinite linear}.ant-badge-status{line-height:inherit;vertical-align:baseline}.ant-badge-status-dot{position:relative;top:-1px;display:inline-block;width:6px;height:6px;vertical-align:middle;border-radius:50%}.ant-badge-status-success{background-color:#54cb0b}.ant-badge-status-processing{position:relative;background-color:#1890ff}.ant-badge-status-processing::after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:50%;animation:antStatusProcessing 1.2s infinite ease-in-out;content:''}.ant-badge-status-default{background-color:#d9d9d9}.ant-badge-status-error{background-color:#f52922}.ant-badge-status-warning{background-color:#fab700}.ant-badge-status-pink{background:#eb2f96}.ant-badge-status-magenta{background:#eb2f96}.ant-badge-status-red{background:#f5222d}.ant-badge-status-volcano{background:#fa541c}.ant-badge-status-orange{background:#fa8c16}.ant-badge-status-yellow{background:#fadb14}.ant-badge-status-gold{background:#faad14}.ant-badge-status-cyan{background:#13c2c2}.ant-badge-status-lime{background:#a0d911}.ant-badge-status-green{background:#52c41a}.ant-badge-status-blue{background:#1890ff}.ant-badge-status-geekblue{background:#2f54eb}.ant-badge-status-purple{background:#722ed1}.ant-badge-status-text{margin-left:8px;color:#6a7580;font-size:13px}.ant-badge-zoom-appear,.ant-badge-zoom-enter{animation:antZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46);animation-fill-mode:both}.ant-badge-zoom-leave{animation:antZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6);animation-fill-mode:both}.ant-badge-not-a-wrapper .ant-badge-zoom-appear,.ant-badge-not-a-wrapper .ant-badge-zoom-enter{animation:antNoWrapperZoomBadgeIn .3s cubic-bezier(.12,.4,.29,1.46)}.ant-badge-not-a-wrapper .ant-badge-zoom-leave{animation:antNoWrapperZoomBadgeOut .3s cubic-bezier(.71,-.46,.88,.6)}.ant-badge-not-a-wrapper:not(.ant-badge-status){vertical-align:middle}.ant-badge-not-a-wrapper .ant-badge-count,.ant-badge-not-a-wrapper .ant-scroll-number-custom-component{transform:none}.ant-badge-not-a-wrapper .ant-scroll-number,.ant-badge-not-a-wrapper .ant-scroll-number-custom-component{position:relative;top:auto;display:block;transform-origin:50% 50%}@keyframes antStatusProcessing{0%{transform:scale(.8);opacity:.5}100%{transform:scale(2.4);opacity:0}}.ant-scroll-number{overflow:hidden;direction:ltr}.ant-scroll-number-only{position:relative;display:inline-block;height:20px;transition:all .3s cubic-bezier(.645, .045, .355, 1);-webkit-transform-style:preserve-3d;-webkit-backface-visibility:hidden}.ant-scroll-number-only>p.ant-scroll-number-only-unit{height:20px;margin:0;-webkit-transform-style:preserve-3d;-webkit-backface-visibility:hidden}.ant-scroll-number-symbol{vertical-align:top}@keyframes antZoomBadgeIn{0%{transform:scale(0) translate(50%,-50%);opacity:0}100%{transform:scale(1) translate(50%,-50%)}}@keyframes antZoomBadgeOut{0%{transform:scale(1) translate(50%,-50%)}100%{transform:scale(0) translate(50%,-50%);opacity:0}}@keyframes antNoWrapperZoomBadgeIn{0%{transform:scale(0);opacity:0}100%{transform:scale(1)}}@keyframes antNoWrapperZoomBadgeOut{0%{transform:scale(1)}100%{transform:scale(0);opacity:0}}@keyframes antBadgeLoadingCircle{0%{transform-origin:50%}100%{transform:translate(50%,-50%) rotate(360deg);transform-origin:50%}}.ant-ribbon-wrapper{position:relative}.ant-ribbon{box-sizing:border-box;margin:0;padding:0;color:#6a7580;font-size:13px;font-variant:tabular-nums;line-height:1.38;list-style:none;font-feature-settings:'tnum';position:absolute;top:8px;height:22px;padding:0 8px;color:#fff;line-height:22px;white-space:nowrap;background-color:#0b68ff;border-radius:3px}.ant-ribbon-text{color:#fff}.ant-ribbon-corner{position:absolute;top:100%;width:8px;height:8px;color:currentcolor;border:4px solid;transform:scaleY(.75);transform-origin:top}.ant-ribbon-corner::after{position:absolute;top:-4px;left:-4px;width:inherit;height:inherit;color:rgba(0,0,0,.25);border:inherit;content:''}.ant-ribbon-color-pink{color:#eb2f96;background:#eb2f96}.ant-ribbon-color-magenta{color:#eb2f96;background:#eb2f96}.ant-ribbon-color-red{color:#f5222d;background:#f5222d}.ant-ribbon-color-volcano{color:#fa541c;background:#fa541c}.ant-ribbon-color-orange{color:#fa8c16;background:#fa8c16}.ant-ribbon-color-yellow{color:#fadb14;background:#fadb14}.ant-ribbon-color-gold{color:#faad14;background:#faad14}.ant-ribbon-color-cyan{color:#13c2c2;background:#13c2c2}.ant-ribbon-color-lime{color:#a0d911;background:#a0d911}.ant-ribbon-color-green{color:#52c41a;background:#52c41a}.ant-ribbon-color-blue{color:#1890ff;background:#1890ff}.ant-ribbon-color-geekblue{color:#2f54eb;background:#2f54eb}.ant-ribbon-color-purple{color:#722ed1;background:#722ed1}.ant-ribbon.ant-ribbon-placement-end{right:-8px;border-bottom-right-radius:0}.ant-ribbon.ant-ribbon-placement-end .ant-ribbon-corner{right:0;border-color:currentcolor transparent transparent currentcolor}.ant-ribbon.ant-ribbon-placement-start{left:-8px;border-bottom-left-radius:0}.ant-ribbon.ant-ribbon-placement-start .ant-ribbon-corner{left:0;border-color:currentcolor currentcolor transparent transparent}.ant-badge-rtl{direction:rtl}.ant-badge-rtl.ant-badge:not(.ant-badge-not-a-wrapper) .ant-badge-count,.ant-badge-rtl.ant-badge:not(.ant-badge-not-a-wrapper) .ant-badge-dot,.ant-badge-rtl.ant-badge:not(.ant-badge-not-a-wrapper) .ant-scroll-number-custom-component{right:auto;left:0;direction:ltr;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl.ant-badge:not(.ant-badge-not-a-wrapper) .ant-scroll-number-custom-component{right:auto;left:0;transform:translate(-50%,-50%);transform-origin:0% 0%}.ant-badge-rtl .ant-badge-status-text{margin-right:8px;margin-left:0}.ant-badge:not(.ant-badge-not-a-wrapper).ant-badge-rtl .ant-badge-zoom-appear,.ant-badge:not(.ant-badge-not-a-wrapper).ant-badge-rtl .ant-badge-zoom-enter{animation-name:antZoomBadgeInRtl}.ant-badge:not(.ant-badge-not-a-wrapper).ant-badge-rtl .ant-badge-zoom-leave{animation-name:antZoomBadgeOutRtl}.ant-ribbon-rtl{direction:rtl}.ant-ribbon-rtl.ant-ribbon-placement-end{right:unset;left:-8px;border-bottom-right-radius:3px;border-bottom-left-radius:0}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner{right:unset;left:0;border-color:currentcolor currentcolor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-end .ant-ribbon-corner::after{border-color:currentcolor currentcolor transparent transparent}.ant-ribbon-rtl.ant-ribbon-placement-start{right:-8px;left:unset;border-bottom-right-radius:0;border-bottom-left-radius:3px}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner{right:0;left:unset;border-color:currentcolor transparent transparent currentcolor}.ant-ribbon-rtl.ant-ribbon-placement-start .ant-ribbon-corner::after{border-color:currentcolor transparent transparent currentcolor}@keyframes antZoomBadgeInRtl{0%{transform:scale(0) translate(-50%,-50%);opacity:0}100%{transform:scale(1) translate(-50%,-50%)}}@keyframes antZoomBadgeOutRtl{0%{transform:scale(1) translate(-50%,-50%)}100%{transform:scale(0) translate(-50%,-50%);opacity:0}}
|