diff --git a/components/common/form/form.css b/components/common/form/form.css index 944bc488..1a738294 100644 --- a/components/common/form/form.css +++ b/components/common/form/form.css @@ -76,6 +76,15 @@ box-shadow: inset 0 0 0 1px var(--github-bgColor-accent-emphasis); } } + /* A field joined to its button (Forgejo's search, .ui.action.input) keeps the join the border above would undo: its + right side is the button's, square and without a line of its own until it has focus. */ + & .ui.action.input:not([class*="left action"]) > input { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + &:not(:focus) { + border-right-color: transparent; + } + } /* A field the server rejected keeps GitHub's red border, which the border above would otherwise replace. */ & .field.error > :is(input, textarea) { border-color: var(--color-error-border); diff --git a/components/common/settings/settings.css b/components/common/settings/settings.css index 25bb7846..f218d8c1 100644 --- a/components/common/settings/settings.css +++ b/components/common/settings/settings.css @@ -130,7 +130,11 @@ font-weight: 500; line-height: 18px; } + /* Forgejo places the right side absolutely, over a long title on a phone; in the row it wraps under it. */ + flex-wrap: wrap; & > :is(.ui.right, .right) { + position: static; + flex: none; display: flex; gap: 8px; margin-left: auto; @@ -236,6 +240,18 @@ } } } + /* A search over a list (runners, the site administration's lists) sits 16px above the list's box, as GitHub's + filter bar does; the repositories' filter menu brings its own margin and divider instead. Unadopted repositories' + field has no search type, and a form that only holds a search field (the token form) has no list under it. */ + & .ui.attached.segment:has(input[type="search"], > form > .ui.action.input):has(+ .ui.attached.segment) { + margin-bottom: 16px; + & > .filter.menu { + margin-bottom: 0; + } + & > .divider { + display: none; + } + } /* An add form below its list (Forgejo's bottom attached segment) sits 16px under the box. */ & .ui.attached.segment + .ui.bottom.attached.segment { margin-top: 16px; diff --git a/styles/components/issues/pull_review.ts b/styles/components/issues/pull_review.ts index e4f79925..4ab15975 100644 --- a/styles/components/issues/pull_review.ts +++ b/styles/components/issues/pull_review.ts @@ -340,6 +340,10 @@ export default css` & svg { color: inherit; } + /* The style's full border would double the seam with the arrow; its border is the line. */ + &:not(:last-child) { + border-inline-end-width: 0; + } } /* GitHub keeps the badge and border neutral for blocked, conflicting, draft and closed pull requests. */ & > .timeline-avatar:is(.red, .grey, .yellow) { diff --git a/styles/components/signin.ts b/styles/components/signin.ts index 9019c289..aa8f59dd 100644 --- a/styles/components/signin.ts +++ b/styles/components/signin.ts @@ -98,12 +98,24 @@ const signIn = css` /* A site-wide username prefix sits in a box joined to the start of the field, with its note below. */ .ui.labeled.input { width: 100%; + /* The site's 32px input height would leave the 40px field hanging below the prefix. */ + height: auto; > .ui.label { display: flex; align-items: center; + margin: 0; + padding: 0 12px; + border: 1px solid ${themeVars.color.input.border}; + border-right: 0; + border-radius: ${otherThemeVars.border.radius} 0 0 ${otherThemeVars.border.radius}; + background: ${themeVars.color.box.header}; font-size: 14px; font-weight: 400; } + > input { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } } .help { display: block; diff --git a/styles/pages/settings.css b/styles/pages/settings.css index 7eb6b365..cbfd7e54 100644 --- a/styles/pages/settings.css +++ b/styles/pages/settings.css @@ -1,5 +1,5 @@ /* Settings sub-pages that need more than the shared settings layout (components/common/settings): two-factor - enrolment, access tokens, webhook deliveries and events, branch protection rules and repository units. */ + enrolment, access tokens, runner setup, webhook deliveries and events, branch protection rules and repository units. */ /* Two-factor enrolment: the QR code in a bordered box, the secret as inline code. */ .page-content > .ui.container.flex-container.theme-settings > .flex-container-main .theme-settings-qr { @@ -94,6 +94,120 @@ } } +/* Runner setup, shown once after a runner is created: the warning as a flash, the UUID and token as rows of a box with + a copy button each, and each snippet in a code block with its copy button in the corner. */ +.page-content > .ui.container.flex-container.theme-settings > .flex-container-main .theme-runner-setup { + & .ui.warning.message { + display: flex; + align-items: flex-start; + gap: 8px; + margin: 0 0 16px; + text-align: start; + & > .svg { + flex: none; + margin-top: 2px; + } + & > p { + margin: 0; + } + } + & .theme-runner-credentials { + margin: 0 0 24px; + border: 1px solid var(--color-light-border); + border-radius: var(--border-radius); + background: var(--color-box-body); + } + & .theme-runner-credential { + display: flex; + align-items: center; + gap: 16px; + min-height: 48px; + padding: 8px 8px 8px 16px; + & + .theme-runner-credential { + border-top: 1px solid var(--color-light-border); + } + & > dt { + flex: none; + width: 64px; + font-weight: 600; + } + & > dd { + display: flex; + flex: 1; + align-items: center; + gap: 8px; + min-width: 0; + margin: 0; + } + & > dd > code { + flex: 1; + min-width: 0; + padding: 0; + background: transparent; + font-size: 12px; + line-height: 20px; + overflow-wrap: anywhere; + } + } + & .theme-runner-setup-heading { + margin: 24px 0 8px; + font-size: 16px; + font-weight: 600; + line-height: 24px; + } + /* The block is drawn by the wrapper, and only the pre scrolls inside it, so a long line passes under the copy button's + column, never under the button. */ + & .theme-runner-snippet { + position: relative; + margin: 0 0 8px; + padding-right: 48px; + border-radius: var(--border-radius); + background: var(--color-markup-code-block); + & > pre { + margin: 0; + padding: 16px 0 16px 16px; + overflow: auto; + border: 0; + border-radius: 0; + background: transparent; + font-family: var(--fonts-monospace); + font-size: 12px; + line-height: 20px; + } + /* Commands and tokens never break: Forgejo wraps code and pre on admin pages with an id selector + (:is(.admin, #detail-modal)), which only !important outranks. */ + & > pre, + & > pre > code { + white-space: pre !important; + overflow-wrap: normal !important; + } + & > pre > code { + padding: 0; + background: transparent; + font: inherit; + } + & > .theme-icon-button { + position: absolute; + top: 8px; + right: 8px; + } + } + & .theme-runner-prompt { + color: var(--color-text-light-2); + user-select: none; + } + & .ui.attached.segment > p { + margin: 0 0 16px; + color: var(--color-text-light-1); + } + & .ui.attached.segment > p > code { + padding: 2px 6px; + border-radius: var(--border-radius); + background: var(--color-markup-code-inline); + font-size: 12px; + } +} + /* Webhook form: the events to choose sit under their radio, GitHub's two columns of checkboxes. */ .page-content.new.webhook > .ui.container.flex-container.theme-settings diff --git a/styles/pages/wiki.css b/styles/pages/wiki.css index 0421ebd4..58cd9ec8 100644 --- a/styles/pages/wiki.css +++ b/styles/pages/wiki.css @@ -351,7 +351,8 @@ margin: 0; padding: 0 8px; border: 1px solid transparent; - border-radius: var(--border-radius); + /* Forgejo squares the first switch for a joined row with !important; here the switches stand apart. */ + border-radius: var(--border-radius) !important; background: transparent; box-shadow: none; color: var(--color-text); @@ -376,6 +377,8 @@ width: 100%; min-width: 0; height: 32px; + /* Forgejo's -1px overlap is for a single row; on its own row it opened a gap before the copy button. */ + margin: 0; padding: 5px 8px; border: 1px solid var(--color-light-border); border-radius: var(--border-radius) 0 0 var(--border-radius); diff --git a/styles/public/base.ts b/styles/public/base.ts index 8c605294..e76c3544 100644 --- a/styles/public/base.ts +++ b/styles/public/base.ts @@ -69,8 +69,8 @@ const body = css` text-underline-position: unset; } } - /* 默认代码块 */ - code:not(.code-inner) { + /* 默认代码块; the code of a block (pre > code) takes its padding from the pre, as on GitHub, so its first line is not indented. */ + code:not(.code-inner, pre > code) { padding: 0.2em 0.4em; } /* 快捷键提示(输入框内) */ diff --git a/styles/public/button.ts b/styles/public/button.ts index 8bb42809..bab92306 100644 --- a/styles/public/button.ts +++ b/styles/public/button.ts @@ -153,7 +153,8 @@ const fixButtonHeight = css` height: 32px; } /* 修复仓库页仓库操作按钮高度对齐和修正 */ - .repo-button-row .ui.button { + .repo-button-row .ui.button, + .repo-button-row .clone-panel > input { min-height: 32px; height: 32px; } diff --git a/styles/public/dropdown/selection_dropdown.ts b/styles/public/dropdown/selection_dropdown.ts index 747d83ce..0f33277f 100644 --- a/styles/public/dropdown/selection_dropdown.ts +++ b/styles/public/dropdown/selection_dropdown.ts @@ -90,6 +90,17 @@ const selectionDropdown = css` .ui.action.input > .dropdown.small:not(:first-child) { border-radius: 0; } + /* The radius rule above counts :has(> #uid) as an id, so a dropdown joined after a field (the admin package type) + repeats it to stay square on its joined sides; before a button, the button's border is the line between them. */ + .ui.action.input > .ui.selection.dropdown:not(:first-child):not(:has(> #uid)) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + &:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right-color: transparent; + } + } /* 排除一些小按钮, 例如软件包类型, 通常相邻有元素 */ .ui.selection.dropdown.active:not(.small) { border-bottom-left-radius: ${otherThemeVars.border.radius} !important; diff --git a/templates/shared/actions/runner_setup.tmpl b/templates/shared/actions/runner_setup.tmpl new file mode 100644 index 00000000..a583e418 --- /dev/null +++ b/templates/shared/actions/runner_setup.tmpl @@ -0,0 +1,52 @@ +{{/* Forgejo's runner setup, shown once after a runner is created, in the shape GitHub gives a credential it shows only +once: the warning as a flash, the UUID and token in a box with a copy button each, and each snippet in a code block +with its own copy button. The copy buttons copy the commands without their "$ " prompts. */}} +
{{.Runner.UUID}}
+
+ {{.Runner.Token}}
+
+ {{$configuration}}
+
+ {{ctx.Locale.Tr "actions.runners.runner_setup.instruction_replace_connection_name"}}
+{{$token}}
+{{$daemon}}
+
+
+ {{ctx.Locale.Tr "actions.runners.runner_setup.instruction_advanced_configurations" (AppDocsURL "admin/actions/")}}
+