Skip to content

Commit e5935e5

Browse files
authored
feat: add clickable badges with extensions to T22 page (solana-foundation#556)
## Description This PR adds clickable bades with extensions to T22 page. ## Type of change - [x] New feature ## Screenshots https://github.com/user-attachments/assets/79c8c23d-868f-4b4e-9b2a-83b1125bb6f1 ## Testing `pnpm t` ## Related Issues solana-foundation#534 ## Checklist - [x] My code follows the project's style guidelines - [x] I have added tests that prove my fix/feature works - [x] All tests pass locally and in CI - [x] I have updated documentation as needed - [x] CI/CD checks pass - [x] I have included screenshots for protocol screens (if applicable) <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Add clickable badges for token extensions on T22 page with Storybook support and tests. > > - **Features**: > - Add clickable badges for token extensions on T22 page in `TokenExtensionsStatusRow.tsx` and `TokenExtensionsSection.tsx`. > - Implement `TokenExtensionBadge` and `TokenExtensionBadges` components for displaying extension statuses. > - Introduce `useTokenExtensionNavigation` hook for managing navigation to token extensions. > - **Storybook**: > - Add Storybook configuration in `.storybook/main.ts` and `.storybook/preview.tsx`. > - Add stories for `TokenExtensionBadge` and `TokenExtensionBadges` in `TokenExtensionBadge.stories.tsx` and `TokenExtensionBadges.stories.tsx`. > - **Testing**: > - Add tests for token extension components using Storybook and Vitest in `vitest.workspace.ts` and `TokenExtensionsStatusRow.stories.tsx`. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=solana-foundation%2Fexplorer&utm_source=github&utm_medium=referral)<sup> for d4bec92. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN -->
1 parent 24d7c6f commit e5935e5

34 files changed

+3175
-380
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,5 @@ jobs:
5858
- name: Test
5959
env:
6060
TEST_SERIAL_TIMEOUT: ${{ vars.TEST_SERIAL_TIMEOUT }}
61-
run: pnpm test:ci
61+
run: |
62+
pnpm test:ci

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ next-env.d.ts
3838
.swc/
3939

4040
# vim
41-
.editorconfig
41+
.editorconfig
42+
*storybook.log

.storybook/layout.min.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.storybook/main.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { StorybookConfig } from '@storybook/experimental-nextjs-vite';
2+
3+
const config: StorybookConfig = {
4+
stories: ['../app/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5+
addons: ['@storybook/addon-essentials', '@storybook/experimental-addon-test'],
6+
framework: {
7+
name: '@storybook/experimental-nextjs-vite',
8+
options: {},
9+
},
10+
staticDirs: ['../public'],
11+
};
12+
export default config;

.storybook/manager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { addons } from '@storybook/manager-api';
2+
import { themes } from '@storybook/theming';
3+
4+
addons.setConfig({
5+
theme: themes.light,
6+
});

.storybook/preview.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { Preview } from '@storybook/react';
2+
import React from 'react';
3+
4+
import { Rubik } from 'next/font/google';
5+
// import './layout.min.css';
6+
import '@/app/styles.css';
7+
8+
const rubikFont = Rubik({
9+
display: 'auto',
10+
subsets: ['latin'],
11+
variable: '--explorer-default-font',
12+
weight: ['300', '400', '700'],
13+
});
14+
15+
const preview: Preview = {
16+
parameters: {
17+
backgrounds: {
18+
values: [{ name: 'Dark', value: '#161b19' }],
19+
default: 'Dark',
20+
},
21+
controls: {
22+
matchers: {
23+
color: /(background|color)$/i,
24+
date: /Date$/i,
25+
},
26+
},
27+
},
28+
decorators: [
29+
Story => (
30+
<div id="storybook-outer" className={rubikFont.className}>
31+
<Story />
32+
</div>
33+
),
34+
],
35+
};
36+
37+
export default preview;

.storybook/vitest.setup.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { beforeAll } from 'vitest';
2+
import { setProjectAnnotations } from '@storybook/experimental-nextjs-vite';
3+
import * as projectAnnotations from './preview';
4+
5+
// This is an important step to apply the right configuration when testing your stories.
6+
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
7+
const project = setProjectAnnotations([projectAnnotations]);
8+
9+
beforeAll(project.beforeAll);

_vitest.workspace.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import path from 'node:path';
2+
import { fileURLToPath } from 'node:url';
3+
4+
import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin';
5+
import { nodePolyfills } from 'vite-plugin-node-polyfills';
6+
import { defineWorkspace } from 'vitest/config';
7+
8+
const dirname = typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url));
9+
10+
// More info at: https://storybook.js.org/docs/writing-tests/test-addon
11+
export const config = defineWorkspace([
12+
'vite.config.mts',
13+
{
14+
extends: 'vite.config.mts',
15+
plugins: [
16+
// The plugin will run tests for the stories defined in your Storybook config
17+
// See options at: https://storybook.js.org/docs/writing-tests/test-addon#storybooktest
18+
storybookTest({ configDir: path.join(dirname, '.storybook') }),
19+
nodePolyfills({
20+
// // To exclude specific polyfills, add them to this list. Note: if include is provided, this has no effect
21+
// exclude: [
22+
// 'http', // Excludes the polyfill for `http` and `node:http`.
23+
// ],
24+
// Whether to polyfill specific globals.
25+
globals: {
26+
Buffer: true, // can also be 'build', 'dev', or false
27+
global: true,
28+
process: true,
29+
},
30+
// To add only specific polyfills, add them here. If no option is passed, adds all polyfills
31+
include: ['path', 'util'],
32+
// // Override the default polyfills for specific modules.
33+
// overrides: {
34+
// // Since `fs` is not supported in browsers, we can use the `memfs` package to polyfill it.
35+
// fs: 'memfs',
36+
// },
37+
// // Whether to polyfill `node:` protocol imports.
38+
// protocolImports: false,
39+
}),
40+
],
41+
test: {
42+
browser: {
43+
enabled: true,
44+
headless: true,
45+
name: 'chromium',
46+
provider: 'playwright',
47+
},
48+
name: 'storybook',
49+
setupFiles: ['.storybook/vitest.setup.ts'],
50+
},
51+
},
52+
]);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { PublicKey } from '@solana/web3.js';
2+
3+
import { TokenExtension } from '../validators/accounts/token-extension';
4+
5+
export const transferFeeConfig0 = {
6+
extension: 'transferFeeConfig',
7+
state: {
8+
newerTransferFee: {
9+
epoch: 200,
10+
maximumFee: 2000000,
11+
transferFeeBasisPoints: 200,
12+
},
13+
olderTransferFee: {
14+
epoch: 100,
15+
maximumFee: 1000000,
16+
transferFeeBasisPoints: 100,
17+
},
18+
transferFeeConfigAuthority: new PublicKey('2apBGMsS6ti9RyF5TwQTDswXBWskiJP2LD4cUEDqYJjk'),
19+
withdrawWithheldAuthority: new PublicKey('3apBGMsS6ti9RyF5TwQTDswXBWskiJP2LD4cUEDqYJjk'),
20+
withheldAmount: 500000,
21+
},
22+
} as TokenExtension;

app/address/[address]/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use client';
2+
import './styles.css';
23

34
import { AddressLookupTableAccountSection } from '@components/account/address-lookup-table/AddressLookupTableAccountSection';
45
import { isAddressLookupTableAccount } from '@components/account/address-lookup-table/types';

0 commit comments

Comments
 (0)