Skip to content

Commit b10d218

Browse files
authored
feat: support custom padding (#26)
1 parent ca9c4de commit b10d218

10 files changed

+140
-45
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ The following props are supported by the `Editor` component:
3333
- `title` (optional): A string representing the title of the editor.
3434
- `controls` (optional): A boolean value indicating whether to display the controls for the editor.
3535
- `lineNumbers` (optional): A boolean value indicating whether to display line numbers in the editor.
36+
- `lineNumbersWidth` (optional): A string representing the width of the line numbers column. The default value is `2.5rem`.
37+
- `padding` (optional): A string representing the padding of the code block. The default value is `1rem`.
3638
- `fontSize` (optional): A string representing the font size of the editor. The default value is `inherit`.
3739

3840
Additionally, you can pass any other props to the `Editor` component, which will be applied to the root `div` element.
@@ -57,10 +59,12 @@ import { Code } from 'codice'
5759

5860
- `title` (optional): A string representing the title of the code block.
5961
- `controls` (optional): A boolean value indicating whether to display the controls for the code block.
60-
- `lineNumbers` (optional): A boolean value indicating whether to display line numbers in the code block.
6162
- `preformatted` (optional): A boolean value indicating whether the code should be displayed as preformatted text. If `true`, the code will be displayed in a `pre` and a `code` element. If `false`, the code will be displayed in a `div` element.
6263
- `asMarkup` (optional): A boolean value indicating whether the code should be displayed as markup. If `true`, the code will be displayed with HTML entities escaped. If `false`, the code will be displayed as plain text. default is `false`.
6364
- `fontSize` (optional): A string representing the font size of the editor. The default value is `inherit`.
65+
- `lineNumbers` (optional): A boolean value indicating whether to display line numbers in the code block.
66+
- `lineNumbersWidth` (optional): A string representing the width of the line numbers column. The default value is `2.5rem`.
67+
- `padding` (optional): A string representing the padding of the code block. The default value is `1rem`.
6468
- `children`: The code content to be displayed in the code block.
6569

6670
### Styling
@@ -74,7 +78,6 @@ Usually you don't need to style the editor, it comes with a default theme. Howev
7478
- `--codice-caret-color`: The color of the caret in the editor. (default: `inherit`)
7579
- `--codice-control-color`: The color of the control items in the code frame and editor. (default: `#8d8989`)
7680

77-
7881
For example, you can define the following CSS variables in your stylesheet to customize the appearance:
7982
```css
8083
:root {

site/app/live-editor.tsx

+46-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { Editor } from 'codice'
4-
import React, { useState } from 'react'
4+
import React, { useId, useState } from 'react'
55
import domToImage from 'dom-to-image'
66

77
const CODE_QUERY_KEY = 'c'
@@ -62,25 +62,35 @@ function Input({
6262
function RangeSelector({
6363
value,
6464
onChange,
65+
text,
66+
min,
67+
max,
68+
step,
6569
className,
6670
...props
6771
}: {
6872
value: number;
73+
text: string;
74+
min: number;
75+
max: number;
76+
step: number;
6977
onChange: (value: number) => void
7078
className: string
7179
}) {
80+
const id = useId()
7281
return (
7382
<div className={className}>
7483
<label
7584
className='controls-manager-label controls-manager-label--checked'
76-
htmlFor="font-size">{`fontSize={`}<b><span>{value}</span></b>{`}`}
85+
htmlFor={id}>{text}{`={`}<b><span>{value}</span></b>{`}`}
7786
</label>
7887
<input
7988
{...props}
89+
id={id}
8090
type="range"
81-
min="12"
82-
max="24"
83-
step="2"
91+
min={min}
92+
max={max}
93+
step={step}
8494
value={value}
8595
onChange={(e) => onChange(Number(e.target.value))}
8696
/>
@@ -140,6 +150,8 @@ export function LiveEditor({
140150
const [controls, setControls] = useState(true)
141151
const [lineNumbers, setLineNumbers] = useState(true)
142152
const [fontSize, setFontSize] = useState(14)
153+
const [padding, setPadding] = useState(1) // rem
154+
const [lineNumbersWidth, setLineNumbersWidth] = useState(2.5) // rem
143155

144156
return (
145157
<div>
@@ -169,7 +181,33 @@ export function LiveEditor({
169181
propName="lineNumbers"
170182
/>
171183
</div>
172-
<RangeSelector className="font-size-control" value={fontSize} onChange={setFontSize} />
184+
<RangeSelector
185+
text="fontSize"
186+
className="range-control"
187+
min={12}
188+
max={24}
189+
step={2}
190+
value={fontSize}
191+
onChange={setFontSize}
192+
/>
193+
<RangeSelector
194+
text="padding"
195+
className="range-control"
196+
min={1}
197+
max={2}
198+
step={0.1}
199+
value={padding}
200+
onChange={setPadding}
201+
/>
202+
<RangeSelector
203+
text="lineNumbersWidth"
204+
className="range-control"
205+
value={lineNumbersWidth}
206+
min={1}
207+
max={2}
208+
step={0.2}
209+
onChange={setLineNumbersWidth}
210+
/>
173211

174212
<div className='editor-layout'>
175213
<span
@@ -195,6 +233,8 @@ export function LiveEditor({
195233
controls={controls}
196234
fontSize={fontSize}
197235
lineNumbers={lineNumbers}
236+
lineNumbersWidth={`${lineNumbersWidth}rem`}
237+
padding={`${padding}rem`}
198238
onChange={(text) => setCode(text)}
199239
/>
200240
</div>

site/app/styles.css

+14-10
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,9 @@ input[type=radio] {
111111
.code-example__item__title {
112112
margin: 0 0 2rem;
113113
}
114-
.controls-manager {
115-
margin: 2rem 0;
116-
}
117114
.controls-manager-label {
118115
display: inline-block;
116+
width: 180px;
119117
padding: 3px 8px;
120118
border-radius: 8px;
121119
cursor: pointer;
@@ -147,21 +145,22 @@ input[type=radio] {
147145
.controls-manager-input::selection {
148146
background-color: #565656;
149147
}
150-
.font-size-control {
151-
margin: 2rem 4px;
148+
.range-control {
149+
font-size: 14px;
150+
margin: 8px auto;
152151
}
153-
.font-size-control label {
152+
.range-control label {
154153
margin-right: 8px;
155154
}
156-
.font-size-control input[type="range"],
157-
.font-size-control input[type="range"]::-webkit-slider-runnable-track {
155+
.range-control input[type="range"],
156+
.range-control input[type="range"]::-webkit-slider-runnable-track {
158157
appearance: none;
159158
-webkit-appearance: none;
160159
background: var(--control-bg-color);
161160
height: 0.5rem;
162161
border-radius: 999px;
163162
}
164-
.font-size-control input[type="range"]::-webkit-slider-thumb {
163+
.range-control input[type="range"]::-webkit-slider-thumb {
165164
appearance: none;
166165
-webkit-appearance: none;
167166
width: 1rem;
@@ -171,11 +170,16 @@ input[type=radio] {
171170
cursor: pointer;
172171
transform: translateY(-0.25rem);
173172
}
173+
.controls-manager {
174+
display: flex;
175+
font-size: 14px;
176+
margin: 0.5rem 0;
177+
}
174178
.controls-manager label span {
175179
font-size: 12px;
176180
}
177181
.controls-manager .control-button {
178-
margin: 4px;
182+
margin-right: auto;
179183
}
180184

181185
.controls-manager input[type="checkbox"] {

src/code/code.test.tsx

+15-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ describe('Code', () => {
1010
--codice-code-highlight-color: #555555;
1111
--codice-control-color: #8d8989;
1212
--codice-font-size: inherit;
13+
--codice-code-line-number-width: 2.5rem;
14+
--codice-code-padding: 1rem;
1315
}
1416
[data-codice-code=":R0:"] pre {
1517
white-space: pre-wrap;
@@ -23,7 +25,7 @@ describe('Code', () => {
2325
width: 100%;
2426
}
2527
[data-codice-code=":R0:"] .sh__line:has(> [data-codice-code-line-number]) {
26-
padding-left: 40px;
28+
padding-left: var(--codice-code-line-number-width);
2729
}
2830
[data-codice-code=":R0:"] .sh__line[data-highlight] {
2931
background-color: var(--codice-code-highlight-color);
@@ -75,6 +77,8 @@ describe('Code', () => {
7577
--codice-code-highlight-color: #555555;
7678
--codice-control-color: #8d8989;
7779
--codice-font-size: inherit;
80+
--codice-code-line-number-width: 2.5rem;
81+
--codice-code-padding: 1rem;
7882
}
7983
[data-codice-code=":R0:"] pre {
8084
white-space: pre-wrap;
@@ -88,7 +92,7 @@ describe('Code', () => {
8892
width: 100%;
8993
}
9094
[data-codice-code=":R0:"] .sh__line:has(> [data-codice-code-line-number]) {
91-
padding-left: 40px;
95+
padding-left: var(--codice-code-line-number-width);
9296
}
9397
[data-codice-code=":R0:"] .sh__line[data-highlight] {
9498
background-color: var(--codice-code-highlight-color);
@@ -173,6 +177,8 @@ describe('Code', () => {
173177
--codice-code-highlight-color: #555555;
174178
--codice-control-color: #8d8989;
175179
--codice-font-size: inherit;
180+
--codice-code-line-number-width: 2.5rem;
181+
--codice-code-padding: 1rem;
176182
}
177183
[data-codice-code=":R0:"] pre {
178184
white-space: pre-wrap;
@@ -186,7 +192,7 @@ describe('Code', () => {
186192
width: 100%;
187193
}
188194
[data-codice-code=":R0:"] .sh__line:has(> [data-codice-code-line-number]) {
189-
padding-left: 40px;
195+
padding-left: var(--codice-code-line-number-width);
190196
}
191197
[data-codice-code=":R0:"] .sh__line[data-highlight] {
192198
background-color: var(--codice-code-highlight-color);
@@ -271,6 +277,8 @@ describe('Code', () => {
271277
--codice-code-highlight-color: #555555;
272278
--codice-control-color: #8d8989;
273279
--codice-font-size: 14px;
280+
--codice-code-line-number-width: 2.5rem;
281+
--codice-code-padding: 1rem;
274282
}
275283
[data-codice-code=":R0:"] pre {
276284
white-space: pre-wrap;
@@ -284,7 +292,7 @@ describe('Code', () => {
284292
width: 100%;
285293
}
286294
[data-codice-code=":R0:"] .sh__line:has(> [data-codice-code-line-number]) {
287-
padding-left: 40px;
295+
padding-left: var(--codice-code-line-number-width);
288296
}
289297
[data-codice-code=":R0:"] .sh__line[data-highlight] {
290298
background-color: var(--codice-code-highlight-color);
@@ -334,6 +342,8 @@ describe('Code', () => {
334342
--codice-code-highlight-color: #555555;
335343
--codice-control-color: #8d8989;
336344
--codice-font-size: 1rem;
345+
--codice-code-line-number-width: 2.5rem;
346+
--codice-code-padding: 1rem;
337347
}
338348
[data-codice-code=":R0:"] pre {
339349
white-space: pre-wrap;
@@ -347,7 +357,7 @@ describe('Code', () => {
347357
width: 100%;
348358
}
349359
[data-codice-code=":R0:"] .sh__line:has(> [data-codice-code-line-number]) {
350-
padding-left: 40px;
360+
padding-left: var(--codice-code-line-number-width);
351361
}
352362
[data-codice-code=":R0:"] .sh__line[data-highlight] {
353363
background-color: var(--codice-code-highlight-color);

src/code/code.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ export function Code({
139139
highlightLines,
140140
preformatted = true,
141141
lineNumbers = false,
142+
lineNumbersWidth,
143+
padding,
142144
asMarkup = false,
143145
...props
144146
}: {
@@ -150,10 +152,12 @@ export function Code({
150152
title?: string
151153
controls?: boolean
152154
lineNumbers?: boolean
155+
lineNumbersWidth?: string
156+
padding?: string
153157
asMarkup?: boolean
154158
} & React.HTMLAttributes<HTMLDivElement>) {
155159
const id = useId()
156-
const styles = css(id, { fontSize, lineNumbers })
160+
const styles = css(id, { fontSize, lineNumbers, lineNumbersWidth, padding })
157161

158162
const lineElements = useMemo(() =>
159163
asMarkup

src/code/css.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ${C} .sh__line {
1515
width: 100%;
1616
}
1717
${C} .sh__line:has(> [data-codice-code-line-number]) {
18-
padding-left: 40px;
18+
padding-left: var(--codice-code-line-number-width);
1919
}
2020
${C} .sh__line[data-highlight] {
2121
background-color: var(--codice-code-highlight-color);
@@ -71,21 +71,25 @@ const lineNumbersCss = (id: string) => `\
7171
content: counter(codice-code-line-number);
7272
display: inline-block;
7373
min-width: calc(2rem - 6px);
74-
margin-left: -40px;
74+
width: var(--codice-code-line-number-width);
75+
margin-left: calc(var(--codice-code-line-number-width) * -1);
7576
margin-right: 16px;
7677
text-align: right;
7778
user-select: none;
7879
color: var(--codice-code-line-number-color);
7980
}
8081
`
8182

82-
8383
export const css = (id: string, {
8484
fontSize,
8585
lineNumbers,
86+
lineNumbersWidth = '2.5rem',
87+
padding = '1rem',
8688
}: {
8789
fontSize: string | number | undefined
8890
lineNumbers: boolean
91+
lineNumbersWidth: string
92+
padding: string
8993
}): string => {
9094
const U = `[data-codice-code="${id}"]`
9195
const fz = fontSizeCss(fontSize)
@@ -95,6 +99,8 @@ ${U} {
9599
--codice-code-highlight-color: #555555;
96100
--codice-control-color: #8d8989;
97101
--codice-font-size: ${fz};
102+
--codice-code-line-number-width: ${lineNumbersWidth};
103+
--codice-code-padding: ${padding};
98104
}
99105
${baseCss(id)}
100106
${headerCss(id)}

src/editor/css.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { fontSizeCss } from '../style'
22

3-
43
export const css = (id: string, {
5-
fontSize
4+
fontSize,
5+
lineNumbersWidth = '2.5rem',
6+
padding = '1rem',
67
}: {
78
fontSize?: string | number
9+
lineNumbersWidth: string
10+
padding: string
811
}) => {
912
const R = `[data-codice-editor="${id}"]`
1013
return `\
@@ -13,6 +16,8 @@ ${R} {
1316
--codice-background-color: transparent;
1417
--codice-caret-color: inherit;
1518
--codice-font-size: ${fontSizeCss(fontSize)};
19+
--codice-code-line-number-width: ${lineNumbersWidth};
20+
--codice-code-padding: ${padding};
1621
1722
position: relative;
1823
overflow-y: scroll;
@@ -27,7 +32,7 @@ ${R} textarea {
2732
line-break: anywhere;
2833
overflow-wrap: break-word;
2934
scrollbar-width: none;
30-
padding: 24px 16px;
35+
padding: calc(var(--codice-code-padding) * 1.5) var(--codice-code-padding);
3136
line-height: 1.5;
3237
font-size: var(--codice-font-size);
3338
caret-color: var(--codice-caret-color);
@@ -61,7 +66,7 @@ ${R} textarea {
6166
overflow: hidden;
6267
}
6368
${R}[data-codice-line-numbers="true"] textarea {
64-
padding-left: 55px;
69+
padding-left: calc(var(--codice-code-line-number-width) + var(--codice-code-padding));
6570
}
6671
`
6772
// line number padding-left is [[width 24px] margin-right 16px] + 15px

0 commit comments

Comments
 (0)