Repository navigation
Rework package token editor like secrets #563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
b81d765
Add package token view edit lifecycle UI
cursoragent 162fedc
Document package token setup URLs
cursoragent 9399d94
Fix package token URL selection feedback
cursoragent 5bea639
Fix token edit browser back behavior
cursoragent d751f7c
Rework package token editor like secrets
cursoragent bdfd431
Merge main into package token rework branch
cursoragent 905b8cf
Address account management review feedback
cursoragent 768ed26
Keep token selected when canceling edit
cursoragent a60f4e4
Disable token selection while mutating
cursoragent 234b0cb
Add generated package token values
cursoragent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
320 changes: 320 additions & 0 deletions
320
packages/worker/client/routes/account-management-components.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,320 @@ | ||
| import { css, type Handle } from 'remix/ui' | ||
| import { on } from '#client/event-mixin.ts' | ||
| import { | ||
| colors, | ||
| mq, | ||
| radius, | ||
| spacing, | ||
| typography, | ||
| } from '#client/styles/tokens.ts' | ||
| import { | ||
| cardCss, | ||
| cardTitleCss, | ||
| descriptionCss, | ||
| fieldLabelCss, | ||
| } from '#client/styles/style-primitives.ts' | ||
|
|
||
| type AccountManagementSlot = any | ||
|
|
||
| type AccountManagementShellProps = { | ||
| maxWidth?: string | ||
| children: AccountManagementSlot | ||
| } | ||
|
|
||
| export function AccountManagementShell( | ||
| handle: Handle<AccountManagementShellProps>, | ||
| ) { | ||
| return () => ( | ||
| <section | ||
| mix={css({ | ||
| maxWidth: handle.props.maxWidth ?? '96rem', | ||
| margin: '0 auto', | ||
| display: 'grid', | ||
| gap: spacing.xl, | ||
| })} | ||
| > | ||
| {handle.props.children} | ||
| </section> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementHeaderProps = { | ||
| title: string | ||
| description: string | ||
| actions?: AccountManagementSlot | ||
| } | ||
|
|
||
| export function AccountManagementHeader( | ||
| handle: Handle<AccountManagementHeaderProps>, | ||
| ) { | ||
| return () => ( | ||
| <header | ||
| mix={css({ | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'flex-start', | ||
| gap: spacing.md, | ||
| flexWrap: 'wrap', | ||
| })} | ||
| > | ||
| <div mix={css({ display: 'grid', gap: spacing.xs })}> | ||
| <h1 | ||
| mix={css({ | ||
| fontSize: typography.fontSize.xl, | ||
| fontWeight: typography.fontWeight.semibold, | ||
| color: colors.text, | ||
| margin: 0, | ||
| })} | ||
| > | ||
| {handle.props.title} | ||
| </h1> | ||
| <p mix={css({ color: colors.textMuted, margin: 0 })}> | ||
| {handle.props.description} | ||
| </p> | ||
| </div> | ||
| {handle.props.actions ? ( | ||
| <div | ||
| mix={css({ | ||
| display: 'flex', | ||
| gap: spacing.sm, | ||
| flexWrap: 'wrap', | ||
| })} | ||
| > | ||
| {handle.props.actions} | ||
| </div> | ||
| ) : null} | ||
| </header> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementMessageProps = { | ||
| children: AccountManagementSlot | ||
| tone?: 'info' | 'error' | ||
| } | ||
|
|
||
| export function AccountManagementMessage( | ||
| handle: Handle<AccountManagementMessageProps>, | ||
| ) { | ||
| return () => ( | ||
| <p | ||
| role="alert" | ||
| mix={css({ | ||
| color: handle.props.tone === 'error' ? colors.error : colors.text, | ||
| margin: 0, | ||
| })} | ||
| > | ||
| {handle.props.children} | ||
| </p> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementLayoutProps = { | ||
| sidebar: AccountManagementSlot | ||
| children: AccountManagementSlot | ||
| sidebarWidth?: string | ||
| } | ||
|
|
||
| export function AccountManagementLayout( | ||
| handle: Handle<AccountManagementLayoutProps>, | ||
| ) { | ||
| return () => ( | ||
| <section | ||
| mix={css({ | ||
| display: 'grid', | ||
| gridTemplateColumns: `${handle.props.sidebarWidth ?? 'minmax(18rem, 22rem)'} minmax(0, 1fr)`, | ||
| gap: spacing.lg, | ||
| alignItems: 'start', | ||
| [mq.mobile]: { | ||
| gridTemplateColumns: '1fr', | ||
| }, | ||
| })} | ||
| > | ||
| {handle.props.sidebar} | ||
| <div mix={css({ display: 'grid', gap: spacing.lg })}> | ||
| {handle.props.children} | ||
| </div> | ||
| </section> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementSidebarProps = { | ||
| title: string | ||
| description: string | ||
| children: AccountManagementSlot | ||
| } | ||
|
|
||
| export function AccountManagementSidebar( | ||
| handle: Handle<AccountManagementSidebarProps>, | ||
| ) { | ||
| return () => ( | ||
| <aside | ||
| mix={css({ | ||
| ...cardCss, | ||
| alignSelf: 'start', | ||
| })} | ||
| > | ||
| <div mix={css({ display: 'grid', gap: spacing.xs })}> | ||
| <h2 mix={css(cardTitleCss)}>{handle.props.title}</h2> | ||
| <p mix={css(descriptionCss)}>{handle.props.description}</p> | ||
| </div> | ||
| {handle.props.children} | ||
| </aside> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementListProps = { | ||
| children: AccountManagementSlot | ||
| maxHeight?: string | ||
| } | ||
|
|
||
| export function AccountManagementList( | ||
| handle: Handle<AccountManagementListProps>, | ||
| ) { | ||
| return () => ( | ||
| <div | ||
| mix={css({ | ||
| maxHeight: handle.props.maxHeight, | ||
| overflowY: handle.props.maxHeight ? 'auto' : undefined, | ||
| overflowX: handle.props.maxHeight ? 'hidden' : undefined, | ||
| paddingRight: handle.props.maxHeight ? spacing.xs : undefined, | ||
| })} | ||
| > | ||
| <ul | ||
| mix={css({ | ||
| listStyle: 'none', | ||
| padding: 0, | ||
| margin: 0, | ||
| display: 'grid', | ||
| gap: spacing.sm, | ||
| })} | ||
| > | ||
| {handle.props.children} | ||
| </ul> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementListItemButtonProps = { | ||
| active: boolean | ||
| onClick: () => void | ||
| children: AccountManagementSlot | ||
| } | ||
|
|
||
| export function AccountManagementListItemButton( | ||
| handle: Handle<AccountManagementListItemButtonProps>, | ||
| ) { | ||
| return () => ( | ||
| <button | ||
| type="button" | ||
| mix={[ | ||
| on('click', handle.props.onClick), | ||
| css({ | ||
| width: '100%', | ||
| minWidth: 0, | ||
| textAlign: 'left', | ||
| display: 'grid', | ||
| gap: spacing.xs, | ||
| padding: spacing.md, | ||
| overflow: 'hidden', | ||
| borderRadius: radius.md, | ||
| border: `1px solid ${ | ||
| handle.props.active ? colors.primary : colors.border | ||
| }`, | ||
| backgroundColor: handle.props.active | ||
| ? colors.primarySoftest | ||
| : colors.background, | ||
| color: colors.text, | ||
| cursor: 'pointer', | ||
| }), | ||
| ]} | ||
| > | ||
| {handle.props.children} | ||
| </button> | ||
| ) | ||
| } | ||
|
|
||
| type AccountManagementPanelProps = { | ||
| title?: string | ||
| description?: string | ||
| children?: AccountManagementSlot | ||
| asForm?: boolean | ||
| onSubmit?: (event: SubmitEvent) => void | ||
| } | ||
|
|
||
| export function AccountManagementPanel( | ||
| handle: Handle<AccountManagementPanelProps>, | ||
| ) { | ||
| const content = () => ( | ||
| <> | ||
| {handle.props.title || handle.props.description ? ( | ||
| <div mix={css({ display: 'grid', gap: spacing.xs })}> | ||
| {handle.props.title ? ( | ||
| <h2 mix={css(cardTitleCss)}>{handle.props.title}</h2> | ||
| ) : null} | ||
| {handle.props.description ? ( | ||
| <p mix={css(descriptionCss)}>{handle.props.description}</p> | ||
| ) : null} | ||
| </div> | ||
| ) : null} | ||
| {handle.props.children} | ||
| </> | ||
| ) | ||
|
|
||
| return () => | ||
| handle.props.asForm ? ( | ||
| <form | ||
| method="post" | ||
| noValidate | ||
| mix={[ | ||
| css(cardCss), | ||
| handle.props.onSubmit | ||
| ? on('submit', (event) => handle.props.onSubmit?.(event)) | ||
| : null, | ||
| ]} | ||
| > | ||
| {content()} | ||
| </form> | ||
| ) : ( | ||
| <section mix={css(cardCss)}>{content()}</section> | ||
| ) | ||
| } | ||
|
|
||
| type MetadataGridProps = { | ||
| items: Array<{ | ||
| label: string | ||
| value: AccountManagementSlot | ||
| }> | ||
| columns?: 2 | 3 | ||
| } | ||
|
|
||
| export function MetadataGrid(handle: Handle<MetadataGridProps>) { | ||
| return () => ( | ||
| <dl | ||
| mix={css({ | ||
| display: 'grid', | ||
| gridTemplateColumns: `repeat(${handle.props.columns ?? 2}, minmax(0, 1fr))`, | ||
| gap: spacing.md, | ||
| margin: 0, | ||
| [mq.mobile]: { | ||
| gridTemplateColumns: '1fr', | ||
| }, | ||
| })} | ||
| > | ||
| {handle.props.items.map((item) => ( | ||
| <div key={item.label}> | ||
| <dt mix={css(fieldLabelCss)}>{item.label}</dt> | ||
| <dd mix={css({ margin: 0, color: colors.text })}>{item.value}</dd> | ||
| </div> | ||
| ))} | ||
| </dl> | ||
| ) | ||
| } | ||
|
|
||
| export const noticeCardCss = { | ||
| display: 'grid', | ||
| gap: spacing.md, | ||
| padding: spacing.lg, | ||
| borderRadius: radius.lg, | ||
| border: `1px solid ${colors.primary}`, | ||
| backgroundColor: colors.primarySoftest, | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.