diff --git a/src/projects/projects-ui.json b/src/projects/projects-ui.json new file mode 100644 index 000000000..689dc7b52 --- /dev/null +++ b/src/projects/projects-ui.json @@ -0,0 +1,186 @@ +{ + "identifier": "projects-ui", + "project_type": "python", + "locale": "en", + "name": "Projects UI", + "user_id": null, + "instructions": [ + { + "quiz": false, + "title": "Print Hello", + "content": "
โก๏ธ Display the word โHelloโ on the screen.
\n\nIn Python, print() outputs strings (words or numbers) to the screen.
Type the code to print() Hello to the screen:
\n\n# Put code to run under here.\nprint(f'Hello')\n\n\n\nThis is what you should see when you run your code.
\n\nHello\n\n\nWhen you type an opening bracket ( the code editor will automatically add a closing bracket ).
\nThis also happens when you type an opening apostrophe '.
If you get an error then check your code really carefully. Check there are single quotes around Hello so Python knows it is meant to be text.
Click the Run button and check that Hello appears in the output.
We have included some variables that store emoji characters.
\n\nA variable is used to store values such as text or numbers. Choosing a sensible name for a variable makes it easier for you to remember what it is for.
\n\n\n\n# variables\nworld = '๐๐๐'\npython = 'Python ๐'\nfire = '๐ฅ'\n\n# Function definitions\n \n# Put code to run under here\nprint(f'Hello')\n\n\n\nClick the Run button and check that the output still says Hello.
โก๏ธ Print the contents of a variable.
\n\nChange your code to also print() the contents of the world variable. You can do this by adding the variable name in curly brackets {}.
\n\n# variables\nworld = '๐๐๐'\npython = 'Python ๐'\nfire = '๐ฅ'\n\n# Function definitions \n \n# Put code to run under here\nprint(f'Hello {world}')\n\n\n\nThis is what you should see when you run your code.
\n\nHello ๐๐๐\n\n\nThe f character inside the print lets you easily print variables along with strings of text.
If you get an error then check you have opened and closed all your brackets () and curly brackets {}.
Click the Run button and check that Hello is followed by the globe emojis.
Add another line to your code to print() more text and emojis:
\n\n# Put code to run under here\nprint(f'Hello {world}')\nprint(f'Welcome to {python}')\n\n\n\nThis is what you should see when you run your code.
\n\nHello ๐๐๐\nWelcome to Python ๐\n\n\nClick the Run button and check that the output has two lines: Hello with the globe emojis and Welcome to Python ๐.
In Python you can work with numbers and dates.
\n\nYou can use arithmetic operators such as + and - to do calculations:
| + | \nadd | \n
| - | \nsubtract | \n
| * | \nmultiply | \n
| / | \ndivide | \n
| ** | \nexponent | \n
Click the Run button and check that the output is still the same as in the previous step, because you have not added any new code yet.
\n", + "position": 4, + "challenge": false, + "completion": [], + "ingredients": [], + "knowledgeQuiz": {} + }, + { + "quiz": false, + "title": "Create a calculation", + "content": "โก๏ธ Print the value of a calculation.
\n\nAdd two more print() lines to your code including a multiplication for Python to calculate:
\n\n# Put code to run under here\nprint(f'Hello {world}')\nprint(f'Welcome to {python}')\nprint(f'{python} is good at maths!')\nprint(f'{111111111 * 111111111}')\n\n\n\nThis is what you should see when you run your code.
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\n\n\nPython uses the same rules for calculations as you might have learned at school. Brackets first, then Orders, Division, Multiplication, Addition, and lastly Subtraction.
\n\nDonโt forget that the UPPERCASE and lowercase letters are important in Python. Always check you are using the correct case.
\n\nClick the Run button and check that your program now prints a maths message and a large number on the next line.
\n", + "position": 5, + "challenge": false, + "completion": [], + "ingredients": [], + "knowledgeQuiz": {} + }, + { + "quiz": false, + "title": "Using modules", + "content": "โก๏ธ Import the datetime module.
Python has many modules that you can use in your code to help perform certain tasks. To use a module, you first need to import it.
\n\nThe datetime module helps with writing code that uses dates and times.
\n\n# imports\nfrom datetime import datetime\n\n# variables\n\n\n\nWhen you run this code, nothing should change, and you should have the same output as the previous step.
\n\nAny text you write in Python with a # in front of it becomes a comment. These lines wonโt run, so they can be useful to help people read and understand your code.
Check that you have spelled datetime correctly, and it is all lowercase.
Run your code and check that the output stays the same as in the previous step after importing datetime.
โก๏ธ Display the current date and time.
\n\nAdd another line to your code to print the current date and time.
Get the current date and time by using the now() function from the datetime module:
\n\nprint(f'{python} is good at maths!')\nprint(f'{111111111 * 111111111}')\nprint(f'The date and time is {datetime.now()}')\n\n\n\nThis is what you should see when you run your code, but the date and time will be different.
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 15:34:10.148000\n\n\nCheck all your brackets () and curly brackets {} to make sure they are all opened and closed in the correct place.
Click the Run button and check that the output now includes a line that starts with The date and time is, followed by the current date and time.
Functions are blocks of code that perform specific tasks.
\n\nThey can be used over and over again.
\n\nHere is an example of a function:
\n\n\n# Function definitions\ndef add_one_and_one():\n x = 1 + 1\n print(x)\n\n\n\nThe name of this function is add_one_and_one.
The code for the task you want the function to do needs to be indented, which means that you need to add four spaces before each line of code.
\n\nCalling a function runs the code inside it. You call a function by using its name. In this case add_one_and_one().
Run your code and check that nothing new is printed yet, because the function has been defined but not called.
\n", + "position": 8, + "challenge": false, + "completion": [], + "ingredients": [], + "knowledgeQuiz": {} + }, + { + "quiz": false, + "title": "Roll dice", + "content": "โก๏ธ Create a function to simulate rolling a dice.
\n\nCreate a function called roll_dice() that prints out the number 4.
\n\n# Function definitions \ndef roll_dice():\n print(f'You rolled a {4}')\n \n# Put code to run under here\n\n\n\nThen, call the function at the bottom of your code.
\n\n\n\nprint(f'The date and time is {datetime.now()}')\nroll_dice()\n\n\n\nThis is what you should see when you run your code.
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 15:55:33.038000\nYou rolled a 4\n\n\nYou can use the Tab key on your keyboard to insert 4 spaces. Pressing Shift and Tab will remove the 4 spaces.
\n\nCheck that you have brackets () and a colon : at the end of your function definition. Also check you are using brackets () when you call your function.
Click the Run button and check that the last line says You rolled a 4.
โก๏ธ Import the randint function from the random module.
Another module called random can be used to create random numbers.
\n\n# imports\nfrom datetime import datetime\nfrom random import randint\n\n\n\nYour code output will not change when you run it.
\n\nRun your code and check that the output stays the same as in the previous step after importing randint.
โก๏ธ Choose a random number for the dice roll.
\n\nUse the randint function you imported to choose a random number between 1 and 6 for the dice roll.
\n\n# Function definitions \ndef roll_dice():\n print(f'You rolled a {randint(1, 6)}')\n \n\n\nNow when you run your code, a new random number between 1 and 6 will be chosen each time.
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 16:02:12.535000\nYou rolled a 6\n\n\nrandint is short for random integer. Integers are whole numbers.
Check your brackets and curly brackets if you get an error. Take note that the same number might be chosen over and over again. Itโs random!
\n\nClick the Run button and check that the last line says You rolled a followed by a number from 1 to 6.
โก๏ธ Multiply the number by the ๐ฅ emoji to print the emoji a number of times equal to the dice roll.
\n\nIn Python you can multiply strings such as emojis or whole words by a number, so they print out several times.
\n\nStore the random number in a variable called roll.
\n\n# Function definitions \ndef roll_dice():\n roll = randint(1,6)\n\n\n\nMultiply the random number stored in roll by the ๐ฅ emoji, and print the result.
\n\n# Function definitions \ndef roll_dice():\n roll = randint(1,6)\n print(f'You rolled a {roll} {fire * roll}')\n \n\n\nYour output code should look something like this:
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 16:14:45.140000\nYou rolled a 4 ๐ฅ๐ฅ๐ฅ๐ฅ\n\n\nCheck all your brackets are the same as the code example above.
\n\nClick the Run button and check that the last line shows the dice number and the same number of fire emojis.
\n", + "position": 12, + "challenge": false, + "completion": [], + "ingredients": [], + "knowledgeQuiz": {} + }, + { + "quiz": false, + "title": "Get input", + "content": "โก๏ธ Allow the person using your program to type in some input.
\n\nYou can use input() to ask the person using your program to enter text, and save it as a variable.
\n\n# Function definitions\ndef roll_dice():\n max = input('How many sides on your dice?:')\n print(f'That is a D {max}')\n roll = randint(1,6)\n print(f'You rolled a {roll} {fire * roll}')\n\n\n\nEnsure you press the Enter key after inputting how many sides.
\nThis is what you should see when you run your code.
Hello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 16:20:41.323000\nHow many sides on your dice?:\n20 \nThat is a D 20\nYou rolled a 1 ๐ฅ\n\n\nClick the Run button, type a number such as 20, and check that the program says That is a D 20 before showing a dice roll.
โก๏ธ Generate a random number between 1 and the number of sides the user typed in.
\n\nInputs are always stored as text, but we need to use the input stored in max to specify the largest number that could be rolled.
max is a string, so it needs changing to an integer int().
\n\n# Function definitions \ndef roll_dice():\n max = input('How many sides on your dice?:')\n print(f'That is a D {max}')\n roll = randint(1, int(max))\n print(f'You rolled a {roll} {fire * roll}')\n \n\n\nThis is what you should see:
\n\nHello ๐๐๐\nWelcome to Python ๐\nPython ๐ is good at maths!\n12345678987654321\nThe date and time is 2023-11-21 16:27:24.101000\nHow many sides on your dice?:12\nThat is a D 12\nYou rolled a 5 ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ\n\n\nChanging one type of data to another type of data is called type casting.
\n\nClick the Run button, type a number of sides, and check that the dice roll can be any number from 1 up to the number you entered.
\n", + "position": 14, + "challenge": false, + "completion": [ + "internal" + ], + "ingredients": [], + "knowledgeQuiz": {} + }, + { + "quiz": false, + "title": "Over to you", + "content": "โก๏ธ Practice adding more print lines to your code.
Here are some sentence starters that you can use:
\n\n\n\n\nroll_dice()\nprint(f'I โค๏ธ ...') \nprint(f'... makes me ๐') \nprint(f'I would like to make ... with {python}')\n\n\n\nHere is a list of some emojis you might like to use:
\n\n๐ ๐ ๐๐ผ ๐๐ฝ ๐๐พ ๐๐ฟ ๐ ๐ ๐จ ๐ฎ ๐ฌ ๐ ๐ถ๏ธ ๐ฒ ๐
\n๐ฆ ๐ ๐ฏ โญ ๐ โค๏ธ ๐ โฝ ๐ ๐ ๐ฅ ๐ โจ ๐ฅบ ๐ ๐ฅ โป๏ธ ๐ณ
\n๐ฉโ๐ฆฝ๐ฉ๐ผโ๐ฆฝ๐ฉ๐ฝโ๐ฆฝ๐ฉ๐พโ๐ฆฝ๐ฉ๐ฟโ๐ฆฝ๐ง ๐ง๐ผ ๐ง๐ฝ ๐ง๐พ ๐ง๐ฟ ๐ ๐๐ผ ๐๐ฝ ๐๐พ ๐๐ฟ
You can copy and paste them into your code.
\n\nClick the Run button and check that your extra print lines show your own words and emojis after the dice roll.
\n", + "position": 15, + "challenge": false, + "completion": [ + "external" + ], + "ingredients": [], + "knowledgeQuiz": {} + } + ], + "components": [ + { + "id": "42b4cdc9-d935-4a3d-b39a-32eb44c5ebfd", + "name": "main", + "extension": "py", + "content": "print(\"Hello World\")" + } + ], + "image_list": [], + "videos": [], + "audio": [] +} diff --git a/src/projects/themes/projects-ui.css b/src/projects/themes/projects-ui.css new file mode 100644 index 000000000..275402343 --- /dev/null +++ b/src/projects/themes/projects-ui.css @@ -0,0 +1,189 @@ +#root { + --cc-blue: hsl(238deg 39% 45% / 100%); + --cc-burgundy: hsl(332deg 48% 26% / 100%); + --cc-cyan: hsl(199deg 74% 54% / 100%); + --cc-dark-green: hsl(166deg 68% 7% / 100%); + --cc-green: hsl(129deg 47% 48% / 100%); + --cc-grey: hsl(237deg 17% 26% / 100%); + --cc-light-yellow: hsl(56deg 88% 78% / 100%); + --cc-off-white: hsl(36deg 38% 95% / 100%); + --cc-orange: hsl(13deg 87% 61% / 100%); + --cc-pink: #f767ab; + --cc-raspberry: var(--rpf-brand-raspberry); + --cc-yellow: hsl(53deg 100% 50% / 100%); + --cc-light-cyan: hsl(199deg 100% 87% / 100%); + --cc-light-green: var(--cc-green-200); + --cc-light-lilac: hsl(239deg 87% 88% / 100%); + --cc-light-orange: hsl(13deg 89% 89% / 100%); + --cc-light-pink: hsl(333deg 100% 91% / 100%); + --cc-pale-cyan: hsl(198deg 91% 96% / 100%); + --cc-pale-green: hsl(127deg 100% 96% / 100%); + --cc-pale-lilac: hsl(240deg 100% 96% / 100%); + --cc-pale-orange: hsl(13deg 100% 97% / 100%); + --cc-pale-pink: hsl(332deg 100% 97% / 100%); + --cc-green-50: hsl(130deg 43% 97% / 100%); + --cc-green-100: hsl(130deg 46% 95% / 100%); + --cc-green-200: hsl(129deg 58% 83% / 100%); + --cc-green-300: hsl(129deg 44% 69% / 100%); + --cc-green-400: hsl(129deg 45% 59% / 100%); + --cc-green-500: var(--cc-green); + --cc-green-600: hsl(129deg 47% 39% / 100%); + --cc-green-700: hsl(129deg 47% 29% / 100%); + + --editor-primary-theme: var(--cc-green); + --editor-secondary-theme: var(--rpf-off-white); + + --code-syntax-1: #005818; + --code-syntax-2: #9d0808; + --code-syntax-3: rgb(153 68 0); + --code-syntax-4: rgb(119 0 136); + --code-syntax-5: rgb(0 0 255); + --code-print-color: var(--rpf-black); + --code-background-color: var(--rpf-white); + --code-block-border-color: var(--rpf-grey-300); + --code-block-line-highlight-color: #ecf8ff; + --code-block-line-highlight-border: 4px solid; + --code-block-line-highlight-border-color: var(--rpf-navy-800); + --code-block-blend-mode: multiply; + --code-text-color: var(--rpf-grey-600); + --code-block-scrollbar-color: var(--rpf-grey-400) var(--rpf-white); + --display-step-counter: flex; + --editor-color-layer-1: var(--rpf-navy-100); + --editor-color-layer-2: var(--rpf-white); + --editor-color-layer-3: var(--rpf-white); + --editor-color-outline: var(--rpf-grey-150); + --editor-color-theme: var(--rpf-black); + --editor-color-theme-secondary: var(--rpf-navy-800); + --editor-color-theme-tertiary: var(--rpf-navy-100); + --editor-color-text: var(--rpf-text-primary); + --editor-color-text-secondary: var(--rpf-text-secondary); + --editor-font-family-sans-serif: lexend, sans-serif; + --editor-htmlrunner-link-display: none; + --editor-logo-display: none; + --project-wrapper-grid-gap: var(--space-2); + --project-editor-wrapper-grid-gap: var(--space-2); + --project-instructions-padding: var(--space-0-5); + --rpf-button-primary-background-color: var(--rpf-black); + --rpf-button-primary-background-color-focus: var(--rpf-black); + --rpf-button-primary-background-color-hover: var(--rpf-grey-800); + --rpf-button-primary-background-color-active: var(--rpf-black); + --rpf-button-primary-background-color-disabled: var(--rpf-navy-200); + --rpf-button-primary-text-color: var(--rpf-white); + --rpf-button-secondary-background-color: var(--rpf-white); + --rpf-button-secondary-background-color-focus: var(--rpf-white); + --rpf-button-secondary-text-color-hover: var(--rpf-grey-600); + --rpf-button-secondary-background-color-active: var(--rpf-grey-600); + --rpf-button-secondary-background-color-disabled: var(--rpf-white); + --rpf-button-secondary-background-color-hover: var(--rpf-grey-50); + --rpf-button-secondary-text-color: var(--rpf-black); + --rpf-button-tertiary-text-color-hover: var(--rpf-grey-600); + --rpf-files-list-item-active: var(--cc-green-200); + --rpf-files-list-item-hover: var(--cc-green-100); + --rpf-input-active-border: var(--editor-color-theme); + --rpf-primary-button-radius: var(--space-10); + --rpf-secondary-button-radius: var(--space-10); + --step-buttons-radius: var(--space-2); + --progress-bar-color: var(--rpf-black); + --project-bar-button-radius: var(--space-10); + --rpf-select-buttons-tick-color: var(--rpf-white); + --rpf-tab-button-background: var(--rpf-off-white); + --rpf-tab-button-hover: var(--rpf-grey-100); + --rpf-tab-border-bottom-selected: var(--rpf-black); + --sidebar-background-selected: var(--rpf-off-white); + --sidebar-border: var(--rpf-grey-150); + --sidebar-border-obscurer-width: 2px; + --sidebar-panel-background: var(--rpf-white); + --sidebar-options-alignment: normal; + --sidebar-footer-padding: 0; + --sidebar-option-hover: var(--rpf-grey-100); + --sidebar-option-selected-border: var(--cc-green-600); + --sidebar-option-selected-background: var(--cc-green-50); + --sidebar-option-selected-background-hover: var(--cc-green-100); + --sidebar-option-selected-icon: var(--cc-green-700); + --tertiary-btn-hover-color: var(--cc-green-100); + + block-size: 100%; + flex: 1 1 auto; +} + +/* + * Theme overrides for editor-wc shadow DOM. + * + * Required since editor-ui 8d1f514: InternalStyles.scss now sets theme tokens + * on #wc.--light, which overrides values inherited from ::part(editor-root). + * + * Injected via host_styles (must use #root #wc for sufficient specificity). + * Keep in sync with ::part(editor-root) in Editor.scss. + */ + +/* stylelint-disable selector-class-pattern */ +#root #wc.--light { + /* Theme colours */ + --editor-color-layer-1: var(--rpf-navy-100); + --editor-color-layer-2: var(--rpf-white); + --editor-color-layer-3: var(--rpf-white); + --editor-color-outline: var(--rpf-grey-150); + --editor-color-theme: var(--rpf-black); + --editor-color-theme-secondary: var(--rpf-navy-800); + --editor-color-theme-tertiary: var(--rpf-navy-100); + --editor-color-text: var(--rpf-text-primary); + --editor-color-text-secondary: var(--rpf-text-secondary); + + /* File list & tabs */ + --rpf-files-list-item-active: var(--cc-green-200); + --rpf-files-list-item-hover: var(--cc-green-100); + --rpf-tab-button-background: var(--rpf-off-white); + --rpf-tab-button-hover: var(--rpf-grey-100); + --rpf-tab-border-bottom-selected: var(--rpf-black); + + /* Sidebar */ + --sidebar-background-selected: var(--rpf-off-white); + --sidebar-border: var(--rpf-grey-150); + --sidebar-panel-background: var(--rpf-white); + --sidebar-option-hover: var(--rpf-grey-100); + --sidebar-option-selected-border: var(--cc-green-600); + --sidebar-option-selected-background: var(--cc-green-50); + --sidebar-option-selected-background-hover: var(--cc-green-100); + --sidebar-option-selected-icon: var(--cc-green-700); +} + +/* Button tokens are scoped to .btn / .rpf-button in InternalStyles */ +#root #wc.--light .btn, +#root #wc.--light .rpf-button { + --rpf-button-background-color: var(--rpf-black); + --rpf-button-border-radius: var(--space-10); + --rpf-button-primary-background-color: var(--rpf-black); + --rpf-button-primary-background-color-focus: var(--rpf-black); + --rpf-button-primary-background-color-hover: var(--rpf-grey-800); + --rpf-button-primary-background-color-active: var(--rpf-black); + --rpf-button-primary-background-color-disabled: var(--rpf-navy-200); + --rpf-button-primary-text-color: var(--rpf-white); + --rpf-button-secondary-background-color: var(--rpf-white); + --rpf-button-secondary-background-color-focus: var(--rpf-white); + --rpf-button-secondary-background-color-hover: var(--rpf-grey-50); + --rpf-button-secondary-background-color-active: var(--rpf-grey-600); + --rpf-button-secondary-background-color-disabled: var(--rpf-white); + --rpf-button-secondary-border-color-hover: none; + --rpf-button-secondary-text-color: var(--rpf-black); + --rpf-button-tertiary-text-color-hover: var(--rpf-grey-600); +} + +#root #wc.--light .rpf-button { + &:hover { + --rpf-button-background-color-hover: var(--rpf-grey-800); + } +} + +/* + * Optional โ only needed if projects-ui ever supports dark mode on editor-wc. + * Adjust values to match your dark theme before enabling. + * +#root #wc.--dark { + --editor-color-theme: var(--cc-green-600); + --sidebar-option-selected-background: var(--cc-green-950); + --sidebar-option-selected-background-hover: var(--cc-green-900); + --sidebar-option-selected-border: var(--cc-green-400); + --sidebar-option-selected-icon: var(--cc-green-300); +} + */ +/* stylelint-enable selector-class-pattern */ diff --git a/web-component.html b/web-component.html index 4d8756389..b5952bda4 100644 --- a/web-component.html +++ b/web-component.html @@ -7,7 +7,8 @@