Skip to content

Commit 5483b50

Browse files
Merge branches 'master' and 'master' of github.com:razorpay/blade
2 parents 5d67c9a + 8f3d52f commit 5483b50

17 files changed

+734
-405
lines changed

.changeset/lovely-chairs-sneeze.md

-12
This file was deleted.

packages/blade/CHANGELOG.md

+38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# @razorpay/blade
22

3+
## 11.2.0
4+
5+
### Minor Changes
6+
7+
- f104cbf3: **feat: Added internationalization in Amount component via i18nify.
8+
References**
9+
10+
- **i18nify-js:** https://www.npmjs.com/package/@razorpay/i18nify-js
11+
- **i18nify-react:** https://www.npmjs.com/package/@razorpay/i18nify-react
12+
13+
**What changes ?**
14+
15+
1. The `<Amount />` component will now automatically format numbers based on the user's browser locale. For example, `<Amount value={123456.789} currency="INR">` will render `₹1,23,456.79` for browsers with the `en-IN` default locale, whereas it will render `₹123,456.79` for browsers with the `en-US` locale.
16+
17+
2. If you want to enable users to change the locale of your page, add the `@razorpay/i18nify-react` package and wrap your app inside the `I18nProvider`. Utilize the `setI18nState` utility to modify the locale. For more details, please refer to the [documentation](https://www.npmjs.com/package/@razorpay/i18nify-react).
18+
19+
3. Additionally, if you prefer to maintain a fixed locale for your page and amount component, enclose your app within `<I18nProvider initData={{locale: 'locale-you-want'}}>..`. For more details, please refer to the [documentation](https://www.npmjs.com/package/@razorpay/i18nify-react).
20+
21+
**How to update ?**
22+
23+
1. Install i18nify as dependency `yarn add @razorpay/i18nify-js`
24+
2. _[Optional]_: Install i18nify-react as dependency to manage state effectively `yarn add @razorpay/i18nify-react`
25+
3. Install latest Blade `yarn add @razorpay/blade@latest`
26+
27+
## 11.1.1
28+
29+
### Patch Changes
30+
31+
- 9801ff86: - feat(Dropdown): add E2E tests
32+
33+
- fix(Dropdown): dropdown getting closed without explicit isOpen={false} in controlled dropdown
34+
35+
> [!Note]
36+
>
37+
> if you have used ControlledDropdown in a similar way how it was documented, things should work fine.
38+
>
39+
> If you have used `isOpen` from Controlled Dropdown but you're not handling it inside `onOpenChange`, you will have to handle that state as well. E.g. `isOpen={isDropdownOpen} onOpenChange={(isOpen) => setIsDropdownOpen(isOpen)}`
40+
341
## 11.1.0
442

543
### Minor Changes

packages/blade/docs/guides/Installation.stories.mdx

+40-35
Original file line numberDiff line numberDiff line change
@@ -40,47 +40,52 @@ Before you install the package, make sure that you have performed the following
4040

4141
## ⬇ Add blade to your application
4242

43-
1. Install blade as a dependency.
44-
Blade has a peer dependency on a few libraries, you can skip adding it if you already have it installed in your project.
43+
1. Install blade as a dependency.
44+
Blade has a peer dependency on a few libraries, you can skip adding it if you already have it installed in your project.
4545

46-
- `styled-components`
46+
```shell
47+
yarn add @razorpay/blade [email protected] @razorpay/i18nify-js @razorpay/i18nify-react
48+
```
49+
50+
- `styled-components`
4751
> **Note**
4852
>
4953
> Currently, blade only supports styled-components v5 only
54+
- `@razorpay/i18nify-js`
55+
- Blade uses this library for formatting capabilities in [Amount](https://blade.razorpay.com/?path=/docs/components-amount--docs) and other components based on the locale. Follow [this guide](https://www.npmjs.com/package/@razorpay/i18nify-js) to install it.
56+
- `@razorpay/i18nify-react`
57+
- A state management React wrapper for `@razorpay/i18nify-js` that maintains locale state of your page. Follow [this guide](https://www.npmjs.com/package/@razorpay/i18nify-react) to configure and install it.
5058

51-
```shell
52-
yarn add @razorpay/blade [email protected]
53-
```
5459
2. Follow [this guide](#-install-fonts) to install the fonts.
5560

56-
3. For **React Native** projects you need to do additional setup for the peer dependencies:
57-
58-
```shell
59-
60-
```
61-
62-
- `react-native-reanimated`
63-
- Follow [this guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation) to install it on Android & iOS which is required by Blade.
64-
- `react-native-svg`
65-
- Follow [this guide](https://github.com/react-native-svg/react-native-svg#with-react-native-cli) to install it on Android & iOS which is required by Blade.
66-
- `react-native-gesture-handler`
67-
- Follow [this guide](https://docs.swmansion.com/react-native-gesture-handler/docs/installation) to install it, note that you don't need to add `<GestureHandlerRootView style={{ flex: 1 }}>` again on the root because BladeProvider already adds that out of the box.
68-
- `@gorhom/bottom-sheet`
69-
- Add this as peer dependency, no need to do additional setup since BladeProvider already sets everything up.
70-
- `@gorhom/portal`
71-
- Add this as peer dependency, no need to do additional setup since BladeProvider already sets everything up.
72-
- `@floating-ui/react-native`
73-
- Add this as peer dependency, no need to do additional setup.
74-
- `react-native-tab-view`
75-
- Add this as peer dependency, no need to do additional setup. This is needed for react-native Tabs component as per [this guide](https://reactnavigation.org/docs/tab-view/#installation).
76-
- `react-native-pager-view`
77-
- Add this as peer dependency, no need to do additional setup. This is needed for react-native Tabs component as per [this guide](https://reactnavigation.org/docs/tab-view/#installation).
78-
79-
And finally run `pod install` command so that blade's RN dependencies are linked to your project:
80-
81-
```shell
82-
cd ios && pod install
83-
```
61+
3. For **React Native** projects you need to do additional setup for the peer dependencies:
62+
63+
```shell
64+
65+
```
66+
67+
- `react-native-reanimated`
68+
- Follow [this guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation) to install it on Android & iOS which is required by Blade.
69+
- `react-native-svg`
70+
- Follow [this guide](https://github.com/react-native-svg/react-native-svg#with-react-native-cli) to install it on Android & iOS which is required by Blade.
71+
- `react-native-gesture-handler`
72+
- Follow [this guide](https://docs.swmansion.com/react-native-gesture-handler/docs/installation) to install it, note that you don't need to add `<GestureHandlerRootView style={{ flex: 1 }}>` again on the root because BladeProvider already adds that out of the box.
73+
- `@gorhom/bottom-sheet`
74+
- Add this as peer dependency, no need to do additional setup since BladeProvider already sets everything up.
75+
- `@gorhom/portal`
76+
- Add this as peer dependency, no need to do additional setup since BladeProvider already sets everything up.
77+
- `@floating-ui/react-native`
78+
- Add this as peer dependency, no need to do additional setup.
79+
- `react-native-tab-view`
80+
- Add this as peer dependency, no need to do additional setup. This is needed for react-native Tabs component as per [this guide](https://reactnavigation.org/docs/tab-view/#installation).
81+
- `react-native-pager-view`
82+
- Add this as peer dependency, no need to do additional setup. This is needed for react-native Tabs component as per [this guide](https://reactnavigation.org/docs/tab-view/#installation).
83+
84+
And finally run `pod install` command so that blade's RN dependencies are linked to your project:
85+
86+
```shell
87+
cd ios && pod install
88+
```
8489

8590
## 🔜 Add blade libraries to your Figma project
8691

@@ -162,4 +167,4 @@ We use 2 fonts. [TASA Orbiter](https://tasatype.localremote.co/) (for our headin
162167
ReactFontManager.getInstance().addCustomFont(this, "TASA Orbiter Display", R.font.tasa);
163168
// rest of the content of the method
164169
}
165-
```
170+
```

packages/blade/package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@razorpay/blade",
33
"description": "The Design System that powers Razorpay",
4-
"version": "11.1.0",
4+
"version": "11.2.0",
55
"license": "MIT",
66
"engines": {
77
"node": ">=18.12.1"
@@ -269,7 +269,9 @@
269269
"typescript": "4.9",
270270
"typescript-transform-paths": "3.4.6",
271271
"@types/body-scroll-lock": "3.1.0",
272-
"ramda": "0.29.1"
272+
"ramda": "0.29.1",
273+
"@razorpay/i18nify-js": "1.4.0",
274+
"@razorpay/i18nify-react": "4.0.0"
273275
},
274276
"peerDependencies": {
275277
"react": ">=18",
@@ -283,7 +285,8 @@
283285
"react-native-svg": "^12.3.0",
284286
"react-native-gesture-handler": "^2.9.0",
285287
"@gorhom/bottom-sheet": "^4.4.6",
286-
"@gorhom/portal": "^1.0.14"
288+
"@gorhom/portal": "^1.0.14",
289+
"@razorpay/i18nify-js": "^1.4.0"
287290
},
288291
"peerDependenciesMeta": {
289292
"react-native": {

packages/blade/src/components/Amount/Amount.stories.tsx

+106-3
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
import type { StoryFn, Meta } from '@storybook/react';
22
import { Title } from '@storybook/addon-docs';
3+
import { getCurrencyList } from '@razorpay/i18nify-js/currency';
4+
import { I18nProvider, useI18nContext } from '@razorpay/i18nify-react';
5+
import { useState } from 'react';
36
import type { AmountProps } from './Amount';
47
import { Amount as AmountComponent } from './Amount';
58
import type { AmountHeadingProps, AmountDisplayProps, AmountBodyProps } from './amountTokens';
6-
import { currencyIndicatorMapping } from './amountTokens';
79
import { getStyledPropsArgTypes } from '~components/Box/BaseBox/storybookArgTypes';
810
import BaseBox from '~components/Box/BaseBox';
911
import { Sandbox } from '~utils/storybook/Sandbox';
1012
import { Display, Text } from '~components/Typography';
1113
import StoryPageWrapper from '~utils/storybook/StoryPageWrapper';
1214
import { Box } from '~components/Box';
1315
import { objectKeysWithType } from '~utils/objectKeysWithType';
16+
import { ActionList, ActionListItem } from '~components/ActionList';
17+
import { SelectInput } from '~components/Input/DropdownInputTriggers';
18+
import { Dropdown, DropdownOverlay } from '~components/Dropdown';
19+
import { Divider } from '~components/Divider';
1420

1521
const Page = (): React.ReactElement => {
1622
return (
1723
<StoryPageWrapper
1824
componentName="Amount"
1925
componentDescription="Amounts are used to show small amount of color coded metadata, which are ideal for getting user attention."
20-
note="This component only displays the provided value in the specified currency, it does not perform any currency conversion."
26+
note="This component only displays the provided value in the specified currency with the formatting capabilities enabled by @razorpay/i18nify-react, it does not perform any currency conversion."
2127
figmaURL="https://www.figma.com/file/jubmQL9Z8V7881ayUD95ps/Blade-DSL?type=design&node-id=73328-558626&mode=design&t=JkDSnlo8KJOBJimR-4"
28+
propsDescription="The Amount component automatically formats numbers based on the user's browser locale enabled by @razorpay/i18nify-react. To adjust the locale according to your page, utilise its hooks for updating the locale. For more details, please refer to
29+
the documentation of @razorpay/i18nify-react library."
2230
>
2331
<Title>Usage</Title>
2432
<Sandbox>
@@ -176,7 +184,7 @@ HumanizeSuffix.args = {
176184
HumanizeSuffix.storyName = 'Humanize Suffix';
177185

178186
const AmountCurrencyTemplate: StoryFn<typeof AmountComponent> = (args) => {
179-
const values = Object.keys(currencyIndicatorMapping);
187+
const values = Object.keys(getCurrencyList());
180188

181189
return (
182190
<BaseBox justifyContent="flex-start" maxHeight="300px" overflowY="auto">
@@ -217,3 +225,98 @@ StrikeThrough.args = {
217225
isStrikethrough: true,
218226
};
219227
StrikeThrough.storyName = 'Strike Through';
228+
229+
// TODO: Replace below with i18nify getDefaultLocales API
230+
const localeList = [
231+
{
232+
country: 'India',
233+
locale: 'en-IN',
234+
},
235+
{
236+
country: 'USA',
237+
locale: 'en-US',
238+
},
239+
{
240+
country: 'Malaysia',
241+
locale: 'ms-MY',
242+
},
243+
{
244+
country: 'France',
245+
locale: 'fr-FR',
246+
},
247+
{
248+
country: 'Germany',
249+
locale: 'de-DE',
250+
},
251+
];
252+
253+
const I18nAmountWrapper = (args: AmountProps): JSX.Element => {
254+
const { setI18nState } = useI18nContext();
255+
const [currency, setCurrency] = useState('INR');
256+
257+
return (
258+
<>
259+
<AmountComponent {...args} currency={currency as AmountProps['currency']} />
260+
<Divider marginY="spacing.4" marginTop="spacing.8" />
261+
<Dropdown selectionType="single">
262+
<SelectInput label="Select currency" />
263+
<DropdownOverlay>
264+
<ActionList>
265+
{Object.keys(getCurrencyList()).map((value) => (
266+
<ActionListItem
267+
key={value}
268+
title={value}
269+
value={value}
270+
onClick={({ name }) => {
271+
setCurrency(name);
272+
}}
273+
/>
274+
))}
275+
</ActionList>
276+
</DropdownOverlay>
277+
</Dropdown>
278+
<Divider marginY="spacing.4" />
279+
<Dropdown selectionType="single">
280+
<SelectInput label="Select locale" />
281+
<DropdownOverlay>
282+
<ActionList>
283+
{localeList.map((item) => (
284+
<ActionListItem
285+
key={item.locale}
286+
title={`${item.country}(${item.locale})`}
287+
value={item.locale}
288+
onClick={({ name }) => {
289+
setI18nState?.({ locale: name });
290+
}}
291+
/>
292+
))}
293+
</ActionList>
294+
</DropdownOverlay>
295+
</Dropdown>
296+
</>
297+
);
298+
};
299+
300+
const I18nAmountTemplate: StoryFn<typeof AmountComponent> = (args) => {
301+
return (
302+
<I18nProvider>
303+
<BaseBox justifyContent="flex-start" minHeight="300px" overflowY="auto">
304+
<BaseBox
305+
display="flex"
306+
alignItems="baseline"
307+
paddingRight="spacing.3"
308+
paddingTop="spacing.3"
309+
flexDirection="column"
310+
>
311+
<I18nAmountWrapper {...args} />
312+
</BaseBox>
313+
</BaseBox>
314+
</I18nProvider>
315+
);
316+
};
317+
318+
export const I18nAmount = I18nAmountTemplate.bind({});
319+
I18nAmount.args = {
320+
...defaultArgs,
321+
};
322+
I18nAmount.storyName = 'Amount in diff locales';

0 commit comments

Comments
 (0)